Обсуждение: Getting the count(*) from two tables and two date ranges in same query

Поиск
Список
Период
Сортировка

Getting the count(*) from two tables and two date ranges in same query

От
Håkan Jacobsson
Дата:

Hi all,

 

I have three tables like this:

 

table1 with column table1_ID

table2 with columns table1_ID,  date  ..etc

table3 with columns table1_ID, date ..etc

 

I would like to create one query to retrieve the rowcount ( count(*) ) from both table2 and table3

 

WHERE date BETWEEN fromdate1 AND todate1

 

in one column in the ResultSet

 

WHERE date BETWEEN fromdate2 AND todate2

 

in another column in the ResultSet

 

WHERE table1_ID = some_value

 

..

Resulting in 4 columns in the ResultSet like:

 

count(*)_from_table2_between_fromdate1_and_todate1  = X       

count(*)_from_table2_between_fromdate2_and_todate2  = Y

count(*)_from_table3_between_fromdate1_and_todate1 = Z

count(*)_from_table3_between_fromdate2_and_todate2  = V

 

Is this possible?

 

/Best regards, Håkan Jacobsson – System developer in Sweden

 

 

 

 

 

 

 

 

 

 

 

Håkan Jacobsson - System Developer

----------------------------------------------------------------

 

RELEVANT TRAFFIC EUROPE AB, Riddarg 17D, SE-114 57 Sthlm, Sweden

 

Mobile (+46) 736 56 97 58

Direct   (+46) 8 56 24 98 05

Phone to office (+46) 8 678 97 50 || Fax (+46) 8 661 19 22

 

Re: Getting the count(*) from two tables and two date ranges in same query

От
"Adam Rich"
Дата:
> Resulting in 4 columns in the ResultSet like:
>
> count(*)_from_table2_between_fromdate1_and_todate1  = X
> count(*)_from_table2_between_fromdate2_and_todate2  = Y
> count(*)_from_table3_between_fromdate1_and_todate1 = Z
> count(*)_from_table3_between_fromdate2_and_todate2  = V
>
> Is this possible?


Select t1.id,
sum(case when t2.date between d1 and d2 then 1 else 0 end) as sum1,
sum(case when t3.date between d1 and d2 then 1 else 0 end) as sum2
from t1, t2, t3
where t1.id=t2.id and t2.id = t3.id
group by t1.id



Re: Getting the count(*) from two tables and two date ranges in same query

От
nathan wagner
Дата:
Adam Rich wrote:
>> Resulting in 4 columns in the ResultSet like:
>>
>> count(*)_from_table2_between_fromdate1_and_todate1  = X
>> count(*)_from_table2_between_fromdate2_and_todate2  = Y
>> count(*)_from_table3_between_fromdate1_and_todate1 = Z
>> count(*)_from_table3_between_fromdate2_and_todate2  = V
>>
>> Is this possible?
>
>
> Select t1.id,
> sum(case when t2.date between d1 and d2 then 1 else 0 end) as sum1,
> sum(case when t3.date between d1 and d2 then 1 else 0 end) as sum2
> from t1, t2, t3
> where t1.id=t2.id and t2.id = t3.id
> group by t1.id

My first thought would be to use a subselect.

select
   (select count(table1_ID) from t2
     where date > fromdate1 and date < todate1)) as X,
   (select count(table1_ID) from t2
     where date > fromdate2 and date < todate2)) as Y,
   (select count(table1_ID) from t3
     where date > fromdate1 and date < todate1)) as Z,
   (select count(table1_ID) from t3
     where date > fromdate2 and date < todate2)) as V
;

No idea if that's the most efficient, but it is more
intuitive to me.  I hadn't really been aware of 'between'.

from
http://www.postgresql.org/docs/8.2/interactive/functions-comparison.html

it seems that

"a BETWEEN x AND y

is equivalent to

a >= x AND a <= y"

Which is wrong (though it may be required by the standard, of course).

1 is not between 1 and 2.  "between" shouldn't include the endpoints.

At any rate, the OP will know what he meant by "between" and can select
the appropriate operators.

--
nathan wagner
nw@hydaspes.if.org

Re: Getting the count(*) from two tables and two date ranges in same query

От
Håkan Jacobsson
Дата:
Hi Adam and all,

I don't get it=). How do I input the second daterange in this query?
Also, I have the ID from table1. Its known in the query.

Wouldn't I need to use a UNION for this kind of query?

Håkan Jacobsson - System Developer
----------------------------------------------------------------

RELEVANT TRAFFIC EUROPE AB, Riddarg 17D, SE-114 57 Sthlm, Sweden

Mobile (+46) 736 56 97 58
Direct   (+46) 8 56 24 98 05
Phone to office (+46) 8 678 97 50 || Fax (+46) 8 661 19 22


-----Ursprungligt meddelande-----
Från: Adam Rich [mailto:adam.r@sbcglobal.net]
Skickat: den 28 januari 2008 15:22
Till: Håkan Jacobsson; pgsql-general@postgresql.org
Ämne: RE: [GENERAL] Getting the count(*) from two tables and two date ranges in same query

> Resulting in 4 columns in the ResultSet like:
>
> count(*)_from_table2_between_fromdate1_and_todate1  = X
> count(*)_from_table2_between_fromdate2_and_todate2  = Y
> count(*)_from_table3_between_fromdate1_and_todate1 = Z
> count(*)_from_table3_between_fromdate2_and_todate2  = V
>
> Is this possible?


Select t1.id,
sum(case when t2.date between d1 and d2 then 1 else 0 end) as sum1,
sum(case when t3.date between d1 and d2 then 1 else 0 end) as sum2
from t1, t2, t3
where t1.id=t2.id and t2.id = t3.id
group by t1.id



Re: Getting the count(*) from two tables and two date ranges in same query

От
nathan wagner
Дата:
Håkan Jacobsson wrote:

  > I don't get it=). How do I input the second daterange in this query?

Through whatever mechanism you are using to issue the query.

 > Also, I have the ID from table1. Its known in the query.

Oops.  I forgot that part in my reply.  So my where clause is
wrong, though easily modified to add "and table1_id = foo".

 > Wouldn't I need to use a UNION for this kind of query?

A union will combine rows (if they're compatible) from two queries,
What you are asking is to assemble columns, which is entirely different.

--
nathan wagner
nw@hydaspes.if.org
Please don't top-post.


Re: Getting the count(*) from two tables and two date ranges in same query

От
Sam Mason
Дата:
On Mon, Jan 28, 2008 at 03:11:10PM +0100, H??kan Jacobsson wrote:
> Resulting in 4 columns in the ResultSet like:
>
> count(*)_from_table2_between_fromdate1_and_todate1  = X
> count(*)_from_table2_between_fromdate2_and_todate2  = Y
> count(*)_from_table3_between_fromdate1_and_todate1 = Z
> count(*)_from_table3_between_fromdate2_and_todate2  = V
>
> Is this possible?

How about something like:

  SELECT x.tbl, d.mn, COUNT(*)
  FROM (
    SELECT 'tbl2' AS tbl, id, date FROM table2
    UNION ALL
    SELECT 'tbl3', id, date FROM table3) x, (VALUES
    ('2001-1-1','2001-12-31'),
    ('2002-1-1','2002-12-31')) d(mn,mx)
  WHERE x.date BETWEEN d.mn AND d.mx
    AND x.id IN (5,6,7,8)
  GROUP BY x.tbl, d.mn
  ORDER BY x.tbl, d.mn;


  Sam

Re: Getting the count(*) from two tables and two date ranges in same query

От
Håkan Jacobsson
Дата:
Adam,

Big thanx - I'll try this out!

Håkan Jacobsson - System Developer
----------------------------------------------------------------

RELEVANT TRAFFIC EUROPE AB, Riddarg 17D, SE-114 57 Sthlm, Sweden

Mobile (+46) 736 56 97 58
Direct   (+46) 8 56 24 98 05
Phone to office (+46) 8 678 97 50 || Fax (+46) 8 661 19 22


-----Ursprungligt meddelande-----
Från: Adam Rich [mailto:adam.r@sbcglobal.net]
Skickat: den 28 januari 2008 16:27
Till: Håkan Jacobsson; pgsql-general@postgresql.org
Ämne: Re: [GENERAL] Getting the count(*) from two tables and two date ranges in same query


Håkan,
You can add as many date ranges as you need:

Select t1.id,
sum(case when t2.date between d1 and d2 then 1 else 0
end) as sum1,
sum(case when t2.date between d3 and d4 then 1 else 0
end) as sum2
sum(case when t3.date between d1 and d2 then 1 else 0
end) as sum3,
sum(case when t3.date between d3 and d4 then 1 else 0
end) as sum4
from t1, t2, t3
where t1.id=t2.id and t2.id = t3.id
group by t1.id

If you know the ID, you can modify slightly:


Select
sum(case when t2.date between d1 and d2 then 1 else 0
end) as sum1,
sum(case when t2.date between d3 and d4 then 1 else 0
end) as sum2
sum(case when t3.date between d1 and d2 then 1 else 0
end) as sum3,
sum(case when t3.date between d3 and d4 then 1 else 0
end) as sum4
from t2, t3
where t2.id = t3.id
and t2.id = 123456



--- Håkan Jacobsson
<hakan.jacobsson@relevanttraffic.com> wrote:

> Hi Adam and all,
>
> I don't get it=). How do I input the second
> daterange in this query?
> Also, I have the ID from table1. Its known in the
> query.
>
> Wouldn't I need to use a UNION for this kind of
> query?
>
> Håkan Jacobsson - System Developer
>
----------------------------------------------------------------
>
> RELEVANT TRAFFIC EUROPE AB, Riddarg 17D, SE-114 57
> Sthlm, Sweden
>
> Mobile (+46) 736 56 97 58
> Direct   (+46) 8 56 24 98 05
> Phone to office (+46) 8 678 97 50 || Fax (+46) 8 661
> 19 22
>
>
> -----Ursprungligt meddelande-----
> Från: Adam Rich [mailto:adam.r@sbcglobal.net]
> Skickat: den 28 januari 2008 15:22
> Till: Håkan Jacobsson; pgsql-general@postgresql.org
> Ämne: RE: [GENERAL] Getting the count(*) from two
> tables and two date ranges in same query
>
> > Resulting in 4 columns in the ResultSet like:
> >
> > count(*)_from_table2_between_fromdate1_and_todate1
>  = X
> > count(*)_from_table2_between_fromdate2_and_todate2
>  = Y
> > count(*)_from_table3_between_fromdate1_and_todate1
> = Z
> > count(*)_from_table3_between_fromdate2_and_todate2
>  = V
> >
> > Is this possible?
>
>
> Select t1.id,
> sum(case when t2.date between d1 and d2 then 1 else
> 0 end) as sum1,
> sum(case when t3.date between d1 and d2 then 1 else
> 0 end) as sum2
> from t1, t2, t3
> where t1.id=t2.id and t2.id = t3.id
> group by t1.id
>
>
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will
> ignore your desire to
>        choose an index scan if your joining column's
> datatypes do not
>        match
>


Re: Getting the count(*) from two tables and two date ranges in same query

От
Håkan Jacobsson
Дата:
Adam,

I don't get the correct row counts when running this SQL.
It seems to produce the correct count when there are no rows found,but not when at least
one row is found (I get a much higher count than when running:

SELECT count(*) FROM table2 WHERE date BETWEEN.....AND table1.id = n

,which is the count I want.)

Might be some problem with the case statement? Or with the

from table2, table3
where table2.table1id = table3.table1id

part?

Very grateful for help!


Håkan Jacobsson - System Developer
----------------------------------------------------------------

RELEVANT TRAFFIC EUROPE AB, Riddarg 17D, SE-114 57 Sthlm, Sweden

Mobile (+46) 736 56 97 58
Direct   (+46) 8 56 24 98 05
Phone to office (+46) 8 678 97 50 || Fax (+46) 8 661 19 22


-----Ursprungligt meddelande-----
Från: Adam Rich [mailto:adam.r@sbcglobal.net]
Skickat: den 28 januari 2008 16:27
Till: Håkan Jacobsson; pgsql-general@postgresql.org
Ämne: Re: [GENERAL] Getting the count(*) from two tables and two date ranges in same query


Håkan,
You can add as many date ranges as you need:

Select t1.id,
sum(case when t2.date between d1 and d2 then 1 else 0
end) as sum1,
sum(case when t2.date between d3 and d4 then 1 else 0
end) as sum2
sum(case when t3.date between d1 and d2 then 1 else 0
end) as sum3,
sum(case when t3.date between d3 and d4 then 1 else 0
end) as sum4
from t1, t2, t3
where t1.id=t2.id and t2.id = t3.id
group by t1.id

If you know the ID, you can modify slightly:


Select
sum(case when t2.date between d1 and d2 then 1 else 0
end) as sum1,
sum(case when t2.date between d3 and d4 then 1 else 0
end) as sum2
sum(case when t3.date between d1 and d2 then 1 else 0
end) as sum3,
sum(case when t3.date between d3 and d4 then 1 else 0
end) as sum4
from t2, t3
where t2.id = t3.id
and t2.id = 123456



--- Håkan Jacobsson
<hakan.jacobsson@relevanttraffic.com> wrote:

> Hi Adam and all,
>
> I don't get it=). How do I input the second
> daterange in this query?
> Also, I have the ID from table1. Its known in the
> query.
>
> Wouldn't I need to use a UNION for this kind of
> query?
>
> Håkan Jacobsson - System Developer
>
----------------------------------------------------------------
>
> RELEVANT TRAFFIC EUROPE AB, Riddarg 17D, SE-114 57
> Sthlm, Sweden
>
> Mobile (+46) 736 56 97 58
> Direct   (+46) 8 56 24 98 05
> Phone to office (+46) 8 678 97 50 || Fax (+46) 8 661
> 19 22
>
>
> -----Ursprungligt meddelande-----
> Från: Adam Rich [mailto:adam.r@sbcglobal.net]
> Skickat: den 28 januari 2008 15:22
> Till: Håkan Jacobsson; pgsql-general@postgresql.org
> Ämne: RE: [GENERAL] Getting the count(*) from two
> tables and two date ranges in same query
>
> > Resulting in 4 columns in the ResultSet like:
> >
> > count(*)_from_table2_between_fromdate1_and_todate1
>  = X
> > count(*)_from_table2_between_fromdate2_and_todate2
>  = Y
> > count(*)_from_table3_between_fromdate1_and_todate1
> = Z
> > count(*)_from_table3_between_fromdate2_and_todate2
>  = V
> >
> > Is this possible?
>
>
> Select t1.id,
> sum(case when t2.date between d1 and d2 then 1 else
> 0 end) as sum1,
> sum(case when t3.date between d1 and d2 then 1 else
> 0 end) as sum2
> from t1, t2, t3
> where t1.id=t2.id and t2.id = t3.id
> group by t1.id
>
>
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will
> ignore your desire to
>        choose an index scan if your joining column's
> datatypes do not
>        match
>


Re: Getting the count(*) from two tables and two date ranges in same query

От
Håkan Jacobsson
Дата:
Adam,

I just realised that issuing the SQL on one table produces the correct count.

SELECT sum(case when table2.date between '2007-07-13' and '2007-07-13' then 1 else 0
end) as sumx FROM table2 WHERE id = n;

This is working alright.
So the problem should lie in the last part:

from table2, table3
where table2.id = table3.id
and table2.id = n;

I think I need the UNION statement instead?

Håkan Jacobsson - System Developer
----------------------------------------------------------------

RELEVANT TRAFFIC EUROPE AB, Riddarg 17D, SE-114 57 Sthlm, Sweden

Mobile (+46) 736 56 97 58
Direct   (+46) 8 56 24 98 05
Phone to office (+46) 8 678 97 50 || Fax (+46) 8 661 19 22


Re: Getting the count(*) from two tables and two date ranges in same query

От
Tom Lane
Дата:
=?iso-8859-1?Q?H=E5kan_Jacobsson?= <hakan.jacobsson@relevanttraffic.com> writes:
> I just realised that issuing the SQL on one table produces the correct count.

> SELECT sum(case when table2.date between '2007-07-13' and '2007-07-13' then 1 else 0
> end) as sumx FROM table2 WHERE id = n;

> This is working alright.
> So the problem should lie in the last part:

> from table2, table3
> where table2.id = table3.id
> and table2.id = n;

It sounds like there are multiple rows in table3 matching the id of (at
least some of) the rows in table2.  You'll get an increment to the sum
for each join pair.

            regards, tom lane

Re: Getting the count(*) from two tables and two date ranges in same query

От
Sam Mason
Дата:
On Wed, Jan 30, 2008 at 09:52:17AM +0100, H??kan Jacobsson wrote:
> I just realised that issuing the SQL on one table produces the correct count.
>
> SELECT sum(case when table2.date between '2007-07-13' and '2007-07-13' then 1 else 0
> end) as sumx FROM table2 WHERE id = n;
>
> This is working alright.
> So the problem should lie in the last part:
>
> from table2, table3
> where table2.id = table3.id
> and table2.id = n;
>
> I think I need the UNION statement instead?

Did you try something similar to the code I posted?


  Sam