Thursday 27 September 2012

Hierarchical Data using mysql

Storing hierarchical data in a relational database is a classic problem. Relational databases are not really designed for this purpose, because they store data in flat rows. Storage is actually the least of our problems. Imagine a commenting system with an unlimited level of nesting in replies. This is easy to store in a relational database:
comment_id
body
parent_id
1 JungleDragon rocks
 
2 No it doesn't!
1
3 Oh yes it does!
2
4 The economy sucks
 
5 True 4
For the sake of simplicity, I have omitted other comment fields such as author, date, etc. The table shows that we can easily store unlimited levels of nesting by simply linking to the parent of the current comment. Comments that have no parent are the root comments, the others are leafs. If we would apply a foreign key to the parent_id column and link it to the id column we even get full referential integrity. 
So far so good? Yes, but the real problems start when we want to query that table for useful stuff. Imagine the following tasks:
  • Get the full comment tree sorted in the correct order. Hint: you cannot use date sorting, since replies can be made anywhere and must be positioned below their parent at all times.
  • For each comment in the tree, we want to know how deep it is (how many levels deep), so we can use that for indenting the comment below its parent.
  • For each comment we want to know how many replies there are, no matter how deep in the tree.
None of the above tasks can be queried efficiently using the table we started with. The problem is that since we do not know how many levels deep the hierarchy is, we need to make recursive calls, leading to many queries to the database, high memory usage in our scripts and generally a system that does not scale.
As said, this is a classic problem, and luckily there are existing solutions and patterns for this. This article explains four different approaches, I highly recommend it. In summary, these are the four methods:
  • Recursive. The approach we already discussed. This approach is inefficient and does not scale.
  • Stack. This one is not much different from the recursive approach. The idea is that you build a stack of hierarchical data by looping through the rows, typically inside a stored procedure. Once you have the stack built, it is very easy to use and query, however, it still requires a lot of database connections.
  • Modified Preorder Tree Traversal. This surely is the most sophisticated, but also most complex, of the methods to work with hierarchical data. I encourage you to read the full description to really understand it. The principle of this method is that we assign smart numbers (left and right) to each leaf in the tree, these numbers indicate the relative position of the node towards other nodes. With a tree preordered like this, querying the hierarchical data becomes very fast and easy. There is a major downfall though: as soon as you insert or change something in the tree, it has to be rebuild. This will lead to many update queries, and these are expensive. The larger the tree, the larger the time of inserting a new node.
  • Flat table model. Surely we know that if we could preprocess things like the level of the comment (how deep is it) and the rank (sort order), querying would become much easier. The author also admits that this does shift the performance problem to the writes: upon inserting a comment, all others ranks have to be recalculated. Anyways, the idea of this model is that you store essential attributes of the tree, instead of calculating them each time we retrieve the tree. Kind of like a tree cache.
Based on the options presented so far, it seems the flat table model looks promising, yet it does have a major limitation: a very expensive write operation. Luckily, one of the commenters of the article posted a way around this. I have taken his idea as a basis, and extended it somewhat.
The Flat Table Model done right
Let's just get to it right away. Here's my(heavily inspired) solution:
comment_id
body
parent_id
lineage deep
1 JungleDragon rocks
  1
0
2 No it doesn't!
1
1-2
1
3 Oh yes it does!
2 1-2-3
2
4 The economy sucks
  4
0
5 True 4 4-5 1
Instead of using a rank, we are using a lineage. They have the same purpose (correctly ordering the comments), it's just that a lineage has one major advantage: it never needs to be updated! As you can see, the lineage column displays the hierarchy ids in a flat column (from highest parent to lowest child). This field is calculated upon insertion, no other inserts need to take place. The deep column simply sets the nesting level of the comment, which is handy when we need this value for indentation later on. By storing it, we require no recursive queries at all.
Let's go into a little bit more detail concerning the insertion of a new comment. Here's how it works:
  • in our save routine of a new comment, we check whether it came from a parent (is parent_id set?)
  • if so, we do a query to retrieve the parent row
  • next, we calculate the lineage and deepness of the new comment. For lineage, we use the parent's lineage. For deepness, we use the parent's deepness + 1.
  • we now insert our new comment. next, we use the returned comment id of the new comment, add it to the lineage of the newly created comment, and save it again (update).
All in all, we are retrieving a row, inserting one, and updating one. Considering the other highly inefficient methods and knowing that most people will read comments and not write them, this is pretty awesome. We have no recursion, not even a regular loop.
Querying this structure is even better. It is super easy to get all comments in the right order, get the indentation, and even the replies per comment, no matter how many levels of nesting we have. This query kind of combines these three tasks:
SELECT c.id, c.user_id, c.body, c.deep, c.lineage, c.parent_id, (SELECT COUNT(*) FROM comment where comment.lineage LIKE (CONCAT(c.lineage,'%')) AND comment.lineage!=c.lineage) as replies
FROM comment as c
order by c.lineage

Careful readers will see that we are using a subquery to count the replies for each comment. This part does have some performance overhead, but not much. If you do not need to show the number of replies to each comment, leave it our for even faster results. Or, you could take this even further by storing the number of replies in the database. The downfall of that approach is that you will need to recursively update all parents of the current comment row. That's not as bad as it sounds, it is not likely that you will have more than a handful of nesting levels for a single comment, in fact, most will have none, one or two.
Referential integrity
What about referential integrity? Since we have flattened the lineage and deep columns, we have lost some of that. No worries though, we are keeping our referential parent_id -> id foreign key. We do have referential integrity at the foundation. Should anything go wrong with the lineage or deep columns, then we can easily use the parent_id -> id relationship to "rebuild" those values.

Usage
The advanced flat model is optimized for a comment system, it should not be used everywhere. Particularly it is suitable for wide trees (little nesting), not deep trees. The reason for this limitation is the lineage column, which flattens the hierarchy in a single column. When there are too many levels of nesting (let's say over 20), a different model may be more suitable.
Yet another way
Throughout my online research, I found yet another way to work with hierarchical data. This approach is again a flat model approach, but this time the author reserves one column per nesting level in the table to store the deepness. The problem is that this results in a hardcoded nesting level limit. The other problem is that it is patented. Go figure. That's like patenting breathing.
Conclusion
There are multiple approaches towards storing and retrieving hierarchical data in (my)SQL, but for comment systems and other wide tree hierarchies, I hope you like my tweaked flat model approach. It has no recursion, not even loops, fast retrieves, the least writes, and a solid foundation of referential integrity. Credits go out to the author of the article and the commenter that suggested the lineage method. I only extended those ideas a little bit.
In closing, I like to end with a small tip. In many online examples, I see people looping through a depth counter to append things like spaces for indentation. This is not needed, almost every language has a function for this, here it is in PHP:
str_repeat("   ",$row['deep']);
...where the first param is the indentation string, and the second param is the number of indentations.
Enjoy!

Tuesday 25 September 2012

T-SQL How to apply recursive queries for organizational charts?

Execute the following Microsoft SQL Server T-SQL recursive scripts in Management Studio Query Editor to get the "immediate supervisor" organizational chart of AdventureWorks Cycles and the number of subordinates at each level.
-- SQL recursive Common Table Expression - CTE - tree processing, tree parsing
-- MSSQL organizational chart - orgchart - direct report - chain of command
USE AdventureWorks;
GO
WITH cteSupervisor(ManagerID,EmployeeID,EmployeeLevel)
     AS (SELECT ManagerID,
                EmployeeID,
                EmployeeLevel = 0
         FROM   HumanResources.Employee
         WHERE  ManagerID IS NULL
         UNION ALL
         SELECT e.ManagerID,
                e.EmployeeID,
                EmployeeLevel + 1
         FROM   HumanResources.Employee e
                INNER JOIN cteSupervisor d
                  ON e.ManagerID = d.EmployeeID)
SELECT Manager = CO.LastName + ', ' + CO.FirstName,
       Employee = C.LastName + ', ' + C.FirstName,
       EmployeeLevel
FROM   cteSupervisor DR
      INNER JOIN HumanResources.Employee E
         ON DR.EmployeeID = E.EmployeeID
      INNER JOIN Person.Contact C
         ON E.ContactID = C.ContactID
      LEFT JOIN HumanResources.Employee EM
         ON DR.ManagerID = EM.EmployeeID
      LEFT JOIN Person.Contact CO
         ON EM.ContactID = CO.ContactID
GO
-- Results
Manager Employee EmployeeLevel
NULL Sánchez, Ken 0
Sánchez, Ken Bradley, David 1
Sánchez, Ken Duffy, Terri 1
Sánchez, Ken Trenary, Jean 1
Sánchez, Ken Norman, Laura 1
Sánchez, Ken Hamilton, James 1
Sánchez, Ken Welcker, Brian 1
Welcker, Brian Jiang, Stephen 2
Welcker, Brian Alberts, Amy 2
Welcker, Brian Abbas, Syed 2
Abbas, Syed Tsoflias, Lynn 3
Alberts, Amy Pak, Jae 3
Alberts, Amy Varkey Chudukatil, Ranjit 3
Alberts, Amy Valdez, Rachel 3
....
------------

-- T-SQL count descendants at each level - count subordinates in organization
-- Parent-child hierarchy - count children by level
DECLARE  @EmployeeID INT,  @Supervisor NVARCHAR(50)

DECLARE curEmployee CURSOR  FOR
SELECT EmployeeID, FullName = FirstName + ' ' + LastName
FROM   AdventureWorks.HumanResources.Employee e
       INNER JOIN AdventureWorks.Person.Contact pc
         ON pc.ContactID = e.ContactID

DECLARE  @Descendant  TABLE(
                            EmployeeID        INT,
                            FullName          NVARCHAR(50),
                            [Level]           INT    NULL,
                            [DescendantCount] INT    NULL
                            )
OPEN curEmployee
FETCH NEXT FROM curEmployee
INTO @EmployeeID, @Supervisor

WHILE (@@FETCH_STATUS = 0 )
  BEGIN
    WITH cteSubTree
         AS (SELECT EmployeeID, 0 AS [Level]
             FROM   AdventureWorks.HumanResources.Employee e
             WHERE  EmployeeID = @EmployeeID -- root
             UNION ALL
             SELECT e.EmployeeID, [Level] + 1 -- recursive term
             FROM   cteSubTree c
                    INNER JOIN AdventureWorks.HumanResources.Employee e
                      ON c.EmployeeID = e.ManagerID)
    INSERT INTO @Descendant
    SELECT   @EmployeeID,
             @Supervisor,
             [Level],
             COUNT(* )  
    FROM     cteSubTree
    GROUP BY [Level]
    FETCH NEXT FROM curEmployee
    INTO @EmployeeID,  @Supervisor
  END

SELECT   FullName,
         [Level],
         DescendantCount,
         t.EmployeeID
FROM     @Descendant t
         INNER JOIN (SELECT   EmployeeID
                     FROM     @Descendant
                     GROUP BY EmployeeID
                     HAVING   count(* ) > 1) g
           ON t.EmployeeID = g.EmployeeID
ORDER BY t.EmployeeID, [Level]
CLOSE curEmployee
DEALLOCATE curEmployee
GO
/*
FullName                Level DescendantCount   EmployeeID
Roberto Tamburello      0     1                 3
Roberto Tamburello      1     7                 3
Roberto Tamburello      2     5                 3
David Bradley           0     1                 6
David Bradley           1     8                 6
JoLynn Dobney           0     1                 7
JoLynn Dobney           1     6                 7
....
*/
------------

Monday 24 September 2012

Latest Update Eset NOD32 Username and Password

It's not tested.  Try to your own risk...TQ

User Name: EAV-71861163
 Password: kvr6cr5tsx
Expire: 20-03-2013
User Name: EAV-71806612
 Password: fckkfn4xaa
Expire: 19-03-2013
Username:EAV-72429849
 Password:vfavknt6kn
Expire:19-10-2012
Username:EAV-72429859
 Password:ehpsvk4b7u
Expire:19-10-2012
Username:EAV-72429855
 Password:hfak57r8p7
Expire:19-10-2012
Username:EAV-72429864
 Password:73xrj4pvx2
Expire:19-10-2012
Username:EAV-72429871
 Password:586k3cm8sx
Expire:19-10-2012
Username:EAV-72522494
 Password:fcb54368xu
Expire:19-10-2012
Username:EAV-72522502
 Password:spr5j54pf8
Expire:19-10-2012
Username:EAV-72522521
 Password:stmv62j5mn
Expire:19-10-2012
Username:EAV-72522516
 Password:n57shpxb56
Expire:19-10-2012
Username:EAV-72522540
 Password:xep2usr2fp
Expire:19-10-2012
User Name:TRIAL-44349774
 Password:mcfv8rasxb
User Name:TRIAL-44349775
 Password:ft8m4ska8p
Username:TRIAL-72994395
 Password:t3nx4bk63v
Username:TRIAL-72994393
 Password:duv3uxv4s7
Username:TRIAL-72994401
 Password:vtf5k2nu7x
Username:TRIAL-72994423
 Password:cvda7hujb8
Username:TRIAL-72994441
Password:3s4var27rm
Username:TRIAL-72994424
 Password:2p657ruckt
Username:TRIAL-72994443
 Password:2mbbkud2ec
Username:TRIAL-72994453
 Password:2udx67e4e5
Username:TRIAL-72994450
 Password:jrm32tr27d
Username:TRIAL-72994455
 Password:s8e4cc6dda
Username:TRIAL-72994475
 Password:b8u25f322u
Username:TRIAL-72994488
 Password:v62u35fpxv
Username:TRIAL-72994491
 Password:u28ac8uhkn
Username:TRIAL-72994505
 Password:5r6xa5b2tb
Username:TRIAL-72994506
 Password:aac8d32hhv
Username:TRIAL-72994514
 Password:kpp4x64t85
Username:TRIAL-72994517
 Password:4uf26jrvft
Username:TRIAL-72994528
 Password:7mtxuthh76
Username: EAV-72408866
Password: cv42hcn73f
Expiry Date: 17.10.2012

Username: EAV-72408895
Password: 78ktdxd2hk
Expiry Date: 17.10.2012

Username: EAV-72408902
Password: 6dsnu8babj
Expiry Date: 17.10.2012

Username:TRIAL-72920639
Password:2ads2kc72r

Username:TRIAL-72920655
Password:eh3jrthncv

Username:TRIAL-72920674
Password:ptjr6vbcph

Username:TRIAL-72920687
Password:rp7n8fuf42

Username:TRIAL-72920706
Password:ahhx233jmf

Username:TRIAL-72920719
Password:cd6u4kkmxx

Username:TRIAL-72920723
Password:pp6nra833m

Username:TRIAL-72810742
Password:7jajtvn578

Username:TRIAL-72810744
Password:d8aenr2s84

Username:TRIAL-72810754
Password:uapb2n82sb

Username:TRIAL-72810764
Password:rhddadfd5x

Username:TRIAL-72810783
Password:fxnhttx7pa

Username:TRIAL-72811872
Password:bjufr5aa2d

Username:TRIAL-72811878
Password:ujt6am7d4v

Username:TRIAL-72811885
Password:cfheunsdbv

PHP e-Book

Are you interested in PHP Programming?
Click a link below:

Tera Copy Pro version

Click here to download teracopy

Internet Downloader Crack Version

Click here to download.

Tuesday 11 September 2012

Free ESET Nod32 Username & Password EAV and Trial 11.09.2012

 
Username:EAV-71912137
Password:vsdtmknmkh
Expire:10-10-2012

Username:EAV-71913126
Password:veuuahddus
Expire:10-10-2012

Username:EAV-71913176
Password:f7puphkxv7
Expire:10-10-2012

Username:EAV-71913221
Password:5rb3n8u86n
Expire:10-10-2012

Username:EAV-71914356
Password:nbvxpncbbn
Expire:10-10-2012

Username:EAV-72011838
Password:2233rn6a2h
Expire:10-10-2012

Username:EAV-72013005
Password:7haxju6mvh
Expire:10-10-2012

Username:EAV-72013069
Password:t6rv5exbbe
Expire:10-10-2012

Username:EAV-72013126
Password:n68bbme7j2
Expire:10-10-2012

Username:EAV-72014393
Password:svk3ks4288
Expire:10-10-2012

Username: TRIAL-72560950
Password: f55u3s4tcr

Username: TRIAL-72560956
Password: ktj2n4nmua

Username: TRIAL-72560959
Password: 5nr4fn2hmj

Username: TRIAL-72560972
Password: 7jd2k8jkx3

Username: TRIAL-72561653
Password: srpra2k584

Username: TRIAL-72561650
Password: upahhka3rd

Username: TRIAL-72560970
Password: f7xnmnj7h7

Username: TRIAL-72561661
Password: 566rr4hmrf

Username: TRIAL-72561663
Password: bs5mkvtbsb

Username: TRIAL-72561660
Password: rxvksbje33

Username: TRIAL-72561680
Password: ar8thvphmh

Username: TRIAL-72561682
Password: bu2e7sbpxr

Username: TRIAL-72561686
Password: 7ven27msef

Username: TRIAL-72561692
Password: bmuskfakx2

Thursday 6 September 2012

Jquery Notification and PHP

Today we learn how to make notification with JQuery and PHP.  Your application must support full JQuery because we don't want any refresh page to see live notification. You need 4 file:

1. index.php     ---- first page with form
2. process.php ---- second page to process parameter
3. checkdata.php ----- third page to check every some interval time
4. jquery.min.js ---- jquery file latest

=======================================================================
Are your ready ? Ok, we start now..

Page 1: index.php

<html>
<head>
 <title>Notification Program</title>
<!-- include jquery latest file here -->
<script src="jquery-1.3.2.js" type="text/javascript"></script>

<script type="text/javascript">
$(document).ready(function(){

        //trigger save button
        $("#save").click(function(){      
                    $.post("process.php",{   
                        phone: $("#phone").val()
                        }, function(data){             
                        alert(data);
                        });
         });

        //check data by interval time every 10000 milisecond (10 sec)
        var old_data = -1; //initial value if you database is empty
        setInterval(function(){
            $.get("checkdata.php",{},function(data){
                if(data > old_count){
                    alert('Database was updated : '+ data + ' records');
                    old_count = data;
                }
            });
        },10000);
       

});
</script>

</head>
<body>
<div id="myform">
    <label>Phone No:</label>
    <input type="text" id="phone" name="phone" />
    <input type="button" id="save" name="btnSave" value="Save" />
</div>

</body>

</html>
======================================================================
Page 2: process.php
This page used to process insert data to database.

<?php

$phone = $_POST['phone'];

//do your connection here

//do your insertion command here

?>

======================================================================
Page 3: checkdata.php

<?php

//this page will running by JQuery timer every 10 sec. Refer Page 1.
//do your connection here

$qry = "SELECT count(*) as total_record from yourtablename";
$result = mysql_query($qry);
$row = mysql_fetch_array($result);

echo $row['total_record'];

?>

=====================================================================
Save your project and run......good luck..




Handle single quotes in HTML,PHP and Javascript

To solve a problem with single quotes PHP and javascript...you should do like this.
Used command str_replace("'","\'", variable);

example:

<script type="text/javascript">
      function deletethis(filename){
      //do something here
      alert(filename);
      }
</script>

<body>

<?php
 $filename = "What's this.pdf";
?>

<a href="javascript:void(0)" id="delfile"
onclick="deletethis('<?php echo str_replace("'", "\'", $filename) ?>')">Padam</a>

</body>