Reputation: 40886
tbl1
type|price
----------
1 | 10
2 | 15
tbl2
type|expires
----------
1 | 2015-01-01
1 | 2017-01-01
1 | 2017-01-01
2 | 2015-01-01
2 | 2017-01-01
I'd like a query that returns data about a given type in tbl1
, and the number of current (non-expired) records of that type in tbl2
. Here is my query:
select tbl1.*,
count(if(tbl2.expires > now(),1,null)) current
from tbl1 left join tbl2
on tbl1.type=tbl2.type
where tbl1.type = 1
As expected, it returns:
type|price|current
1 | 10 | 2
However, when I ask for a non existent type, I expect 0 result. However, if I replace the type in the query to 3
, I get:
type|price|current
NULL|NULL | 0
Please help me understand
type
)Upvotes: 0
Views: 85
Reputation: 733
Try this query:
SELECT
tbl1.type
,tbl1.price
,count(A.expires)
FROM tbl1
INNER JOIN
(
SELECT
tbl2.type
,tbl2.expires
FROM tbl2
WHERE tbl2.expires > now()
) AS A
ON tbl1.type = A.type
WHERE tbl1.type = 3
GROUP BY tbl1.type
Just for your information: Although the above query works but isn't compatible with SQL Server or other SQL Products and won't work there.
Below query would work with any SQL Product which supports inner join and date functions to get the current date. Only change that would be required be to replace Now() with similar function in target sql product.
MySql appears to be linient in some aspects.
SELECT
tbl1.Type
,tbl1.Price
,A.ExpCount
FROM tbl1
INNER JOIN
(
SELECT
tbl2.Type
,COUNT(tbl2.Expires) ExpCount
FROM tbl2
WHERE tbl2.expires > NOW()
GROUP BY tbl2.Type
) AS A
ON tbl1.type = A.type
WHERE tbl1.type = 1
Upvotes: 1
Reputation: 11
SELECT T.* , (SELECT COUNT(*) FROM TBL2 WHERE TYPE = T.TYPE AND EXPIRES >= SYSDATE ) current
FROM TBL1 T
WHERE T.TYPE = 1 ;
/* IF TBL2.EXPIRES DATA TYPE IS NOT DATE AT FIRST YOU SHOULD MAKE IT DATE *\
Upvotes: 0
Reputation: 40886
Thanks for your responses. After learning first from Giorgos that aggregate functions without a group by
always return something, I just added a group by
clause. Here is my selected query:
select tbl1.*, count(*) current
from tbl1 left join tbl2
on tbl1.type=tbl2.type
where tbl1.type=3 and tbl2.expires > now()
group by tbl1.type
Thanks all.
Upvotes: 0
Reputation: 3675
I would try this:
select type , count(counter) from (
select tbl1.type type,tbl2.expires counter
from tbl1 left join tbl2
on tbl1.type=tbl2.type
where tbl1.type = 1
and tbl2.expires > now()
) t
group by type ;
The difference is that in your query you are still returning something when there is no matching data (if(tbl2.expires > now(),1,null)
).
Upvotes: 2
Reputation: 72165
Using an aggregate function like count
without a group by
clause returns always exactly one row.
A work-around is to wrap your query in a subquery and check for type
again in the outer query:
select *
from (
select tbl1.*,
count(if(tbl2.expires > now(),1,null)) current
from tbl1
left join tbl2 on tbl1.type=tbl2.type
where tbl1.type = 3) as t
where type = 3
Upvotes: 1
Reputation: 13700
You should note that all aggregate queries will return at least single row as result
Look at this example
SELECT 1
where 1=0;
The above returns empty result. But the following
SELECT SUM(1)
where 1=0;
Returns NULL as single row
Upvotes: 1