Getting Parent Table entries comparing Child fields.

Login or register to post comments
18 replies [Last post]
Offline
Joined: 04/09/2009

Hi all,

I have a parent table and a child table. I need the parent table entry comparing on the child table.

Here goes my scenario:

ReqHeader:
ReqID
CreatedOn
Text

ReqItem:
ReqID
Date
Status

Now I want all the entries from ReqHeader with only those 3 columns where ReqItem.Date is between two dates and ReqItem.Status equal a Status. I have two SQL queries for illustration using join and query inside a query:

  1. select h.ReqID, h.ClientID, h.CreatedOn, h.Text From reqheader as h join reqitem as i on h.ReqID = i.ReqID where
    i.date between '20090501' and '20090607' and Status = 2;
  2. select * from reqheader where ReqID in (select ReqID from reqitem where date between '20090501' and '20090607' and Status = 2);

Both of them give the same result. As shown I only need columns from the header table with no repetition.

I have done simple qcubed queries involving single table but not multiple. I am confused on how to implement it in Qcubed using QQ queries or otherwise.

Please help me implement most optimized solution out of the three. Later I would be displaying the results in a datagrid on the dialog panel.

Thanks.

Offline
Joined: 03/31/2008

Is there an actual Req table which relates to these IDs? What are the SQL relationships between the two ReqID columns?

In theory, you should be able to do something like:

<?php
$headers
= ReqHeader::QueryArray(
 
QQ::AndCondition(
   
QQ::Between(QQN::ReqHeader()->Req->ReqItems->Date, '2009-05-01', '2009-06-07'),
   
QQ::Between(QQN::ReqHeader()->Req->ReqItems->Status, 2)
  )
);
?>

Offline
Joined: 04/09/2009

Thank you Vexed Panda.

The relationship the tables share is only through ReqID and there is no other table. ReqID is primary key for ReqHeader table and ReqItem has ReqID and Item as primary key. In my relationship.txt file I have defined:
ReqItem.ReqID => ReqHeader.ReqID

I tried QQN::ReqHeader()->ReqItems->Date but I got the error: "Undefined GET property or variable in 'QQNodeReqheader' class: ReqItems". Please help.

Thanks.

agsel's picture
Offline
Joined: 04/02/2008

If you generated your code, did it show you that one of those tables has any relationships? It seems that qcubed doesn't know about your relationship.

Offline
Joined: 04/09/2009

I got the message that ReqItem is created with relationships.

agsel's picture
Offline
Joined: 04/02/2008

First, you probably don't have property name in plural form. Instead of "ReqHeader()->ReqItems" you probably have "ReqHeader()->ReqItem".

You can look up the class "QQNodeReqheader" and see, which properties does it have (in __get method). It should be located in file "includes/data_classes/generated/ReqheaderGen.class.php" or similar.

Offline
Joined: 04/09/2009

I changed the name to singular yet same message. I have attached my ReqHeaderGen.class.php here: http://pastebin.com/m4d867f6b

Not sure why its not working. Please help. Thanks.

Offline
Joined: 03/31/2008

It looks like the name is actually ReqitemAsReqid, so in my example code, you should be able to replace Req->ReqItems with ReqitemAsReqid.

Offline
Joined: 04/09/2009

Thanks a lot Vexed Panda, it worked.

But the name gives me jitters. As your filtered data grid also doesn't work in my qcubed implementation. Do you think there might be something screwed up with my Qcubed?

Offline
Joined: 03/31/2008

No, I'd say your code looks pretty normal. The shared primary key approach is unusual, causing the unusual name for the relationship, but functionally it should work great.

I'll try and find more time to look into your issues with QFilteredDataGrid, since it really should be working from what I've seen.

Offline
Joined: 04/09/2009

Thank you.

Two more things regarding querires:

  1. I wanted to get the distinct records in this query and thought of trying QQ::Distinct for the query. But could not do it. Used normal array_unique function:
    <?php
     
    return array_unique(ReqHeader::QueryArray(
                   
    QQ::AndCondition(QQ::Equal(QQN::Reqheader()->ClientID, $clientID),
                   
    QQ::GreaterOrEqual(QQN::ReqHeader()->ReqitemAsReqid->Date, $dttStartDate),
                   
    QQ::LessOrEqual(QQN::Reqheader()->ReqitemAsReqid->Date, $dttEndDate),
                   
    QQ::Like(QQN::Reqheader()->ReqitemAsReqid->Status, $numStatus))
                    ));   
    ?>
  2. As you see on the query I am using two DateTime parameters, I could not use the QQ::Between too as it was not able to conevert DateTime to string, I think Between works only on string and not on date.

Currently I am happy with the query as it works. But using OO db seems more fun.

alex94040's picture
Offline
Joined: 11/06/2008

meetsang,

When I troubleshoot my own QQuery stuff, I find it useful to see what SQL expressions QQuery is generating - this helps me understand where I screwed up (and it's usually my fault, not QQuery's :-)).

I'd recommend you to do the same for both of your questions, and analyze the SQL yourself - if you need help, do post it here.

Offline
Joined: 05/15/2009

If you want to get distinct records you can include in the clause:

return ReqHeader::QueryArray(
                QQ::AndCondition(QQ::Equal(QQN::Reqheader()->ClientID, $clientID),
                QQ::GreaterOrEqual(QQN::ReqHeader()->ReqitemAsReqid->Date, $dttStartDate),
                QQ::LessOrEqual(QQN::Reqheader()->ReqitemAsReqid->Date, $dttEndDate),
                QQ::Like(QQN::Reqheader()->ReqitemAsReqid->Status, $numStatus)),
                QQ::Clause(QQ::Distinct())
                )

If you want to get more precise distinct eg SELECT DISTINCT regheader.client_id from regheader, I think you must use custom Query.

Offline
Joined: 04/09/2009

Thank you revvi, that worked.

Alex, thank you for the tip, I am reading Qcubed code sometimes. I know it helps a lot.

Offline
Joined: 03/31/2008

I use between with dates with no issues. Whats worth pointing out though is that if you're comparing dates, "2009-01-01" < "2009-01-01 12:01am". So if you meant to cover the entirety of "2009-01-01", you should probably be using 2009-01-02 - 1 millisecond instead.

alex94040's picture
Offline
Joined: 11/06/2008

I just tried using QQ::Between on QDateTimes, and it does not work.

$beforeDate = QDateTime::Now();
$beforeDate->AddDays(-30);

$afterDate = QDateTime::Now();
$afterDate->AddDays(-29);

$employers = Employer::QueryArray(
   QQ::Between(QQN::Employer()->RegistrationDate,
        $beforeDate,
        $afterDate)
);

I get the following error: Unable to cast QDateTime object to string

This is because the QQConditionBetween constructor tries to cast the operands into strings, and that fails. The following does work, though:

$employers = Employer::QueryArray(
   QQ::Between(QQN::Employer()->RegistrationDate,
        $beforeDate->__toString('YYYY-MM-DD'),
        $afterDate->__toString('YYYY-MM-DD')));

We should fix this to allow dates to work explicitly, without these tricks.

Offline
Joined: 07/20/2009

Thanx Alex above code helps me a lot..

once again thanx a lot

mcluver's picture
Offline
Joined: 07/31/2009

Revvi,

You're exactly right! Apparently there is no option but to use an ad-hoc SQL query for statements like this: SELECT DISTINCT table.field from table;

I've been trying to populate a QListbox with the distinct database FIELD results - which seems to me like it would be a very common task when developing a web 2.0 system (especially in regards to creating a dynamic Select Input).

Obviously everyone is going to automatically expect that functionality from a feature called QQ::Distinct -- maybe I just expect too much.

To see the reasoning behind this omission in the original framework - take a look here: http://www.qcodo.com/forums/forum.php/2/1669

And then to not even mention it in the Examples documentation!

I mean don't get me wrong, Mike's response makes total sense from a logical programming standpoint - but from an expectation of the code's response perspective (for the average programmer), it is a complete FAIL.

Are there more curve-balls like this that I should be expecting as I learn to work with Qcubed?

alex94040's picture
Offline
Joined: 11/06/2008

The underlying reason behind this lack of support for field-level SELECT DISTINCT is that QCubed does not allow you to pick and choose e database columns you want as a result of your QQuery. This, of course, means that every single field is selected with every query, and select distinct only gets you wholesale distinct records, which is not what you want.

We do want to add support for column selection into QQuery, but its quite a complex undertaking. You can see a related discussion in this thread: http://qcu.be/content/memory-limit-error This thread also has a few great links in there, do review them if you are deeplyinterested in this subject.

You're right that we should probably write an example article on this subject. Would you be up for doing it, mcluver? This would really help the community.