Select all from one table and count from another and include nulls - sql

I'm trying to get all ids from one table and a count of transactions from another table. The trick is that an id may not be listed in the transaction table. In that case, I want the query to return 0 for that id. (I apologize for the bad formatting)
ID Table
ID
1
2
3
Trans Table
ID Trans
1 123
1 234
3 345
3 456
3 567
Query results
ID - Trans Count
1 2
2 0
3 3
I have this code, but it just isn't working for me and I can't figure out why.
SELECT A.ID, COUNT (B.TRANS) AS CNT
FROM A
LEFT JOIN B
ON A.ID = B.ID
WHERE B.DTE BETWEEN '01-Mar-2017' AND '31-Mar-2017' AND
A.CURRENT_FLAG = 1
GROUP BY A.ID

When using left join, conditions on the first table go in the where clause. Conditions on the second table go in the on clause:
SELECT A.ID, COUNT (B.TRANS) AS CNT
FROM A LEFT JOIN
B
ON A.ID = B.ID AND
B.DTE BETWEEN '01-Mar-2017' AND '31-Mar-2017' AND
WHERE A.CURRENT_FLAG = 1
GROUP BY A.ID;

I would check if the value is null if then just replace it with a 0
The NVL Function will work perfect for this scenario.
SELECT A.ID, COUNT (NVL(B.TRANS,0)) AS CNT
FROM A
LEFT JOIN B
ON A.ID = B.ID
WHERE B.DTE BETWEEN '01-Mar-2017' AND '31-Mar-2017' AND A.CURRENT_FLAG = 1
GROUP BY A.ID

Related

Return 1 result with left join from table B

Table A Table B Table B Table B
Itemnr Itemnr Item Status Remark
100000 100000 1 Approved
200000 100000 2 Use up
100000 3 Obsolete
200000 1 Approved
200000 2 Use up
200000 3 Obsolete
I would like to see only one result per line in table A item with as result the Remark based on Item status 1. I tried a lot with the option of a left join but without the good result.
Is this what you want?
select a.itemnr, b.remark
from tablea a
inner join tableb b on b.itemnr = a.itemnr and b.item_status = 1
If some records in tablea might not have a corresponding row in tableb with item_status = 1 and you want to keep these in the resultset, then you can use left join instead of inner join.
For the data example you have provided, you don't need tablea:
select b.itemnr, b.remark
from tableb b
where b.item_status = 1;
You specify that you want a left join, which implies rows in tablea that are not in tableb, although you have no such examples in the question. In that case:
select a.itemnr, b.remark
from tablea a left join
tableb b
on b.itemnr = a.itemnr and b.item_status = 1;
You can use row_number()
select t.*
from (select a.*, b.*, row_number() over (partition by a.itemr order by b.status) as seq
from a inner join
b
on a.itemr = b.itemr
) t
where seq = 1;
This will return rows total itemrs along with first status. Also this assumes Itemnr, Item Status, Remark are the columns name.
EDIT : If you want to check, first status 1 is available or not then you can do :
SELECT a.itemr, b.remark
FROM a LEFT JOIN
b
ON b.itemr = a.itemr AND b.status = 1;

T-SQL - Equal to both but not either

I'm trying to write a simple query where each ID needs to have both Product A AND B but not either. In my example, I only want ID #3 and the Product's of each to return as none of the other ID's will fit this criteria.
I've taken a look at Count/ Rank/ Row_Number and can't seem to figure this one out. Maybe I'm looking at it the wrong way. Any ideas?
ID Product
1 A
2 A
3 A
3 A
3 B
4 A
5 B
6 B
6 B
Using group by and having.
select id
from tbl
where product in ('A','B')
group by id
having count(distinct product) = 2
If there are only 2 products, you can self-join your table:
SELECT A.ID, A.Product, B.Product FROM [table] A INNER JOIN [table] B ON A.ID = B.ID AND A.Product != B.Product

SQL: group function is not allowed here

I have this query
SELECT * FROM TABLEA A
INNER JOIN TABLEB B ON A.ID = B.ID AND COUNT(B.*) < 4
WHERE A.STATUS = 0
In tablea, ID will have 2 row of data(2 entries), but in tableb the same ID will have upto 4 rows of data. I am trying to get the ID that has less than 4 rows of data in tableb and display that result.
so if ID 12345 is having only 2 rows of data in tableb, display that result. IF ID 98765 has 4 rows of data in tableb, ignore this entry.
But when i try the above query it says "group function is not allowed here". Please can someone help.
You can not use count() without goup by or having clause. In your case you need having
SELECT * FROM TABLEA A
INNER JOIN TABLEB B ON A.ID = B.ID
WHERE A.STATUS = 0
having COUNT(B.*) < 4
see the sqlfiddle
write it the way you would say it...
"I am trying to get the ID that has less than 4 rows of data in tableb and display that result"
SELECT * FROM TABLEA a
JOIN TABLEB b ON b.ID = a.ID
WHERE A.STATUS = 0
and (Select count(*) from TABLEB
where id = a.Id) < 4
it's not clear, but if you also only want Ids which have 2 or more rows in TableA:
SELECT * FROM TABLEA a
JOIN TABLEB b ON b.ID = a.ID
WHERE A.STATUS = 0
and (Select count(*) from TABLEB
where id = a.Id) < 4
and (Select count(*) from TABLEA
where id = a.Id) > 1

select sql query to merge results

I have a table old_data and a table new_data. I want to write a select statement that gives me
Rows in old_data stay there
New rows in new_data get added to old_data
unique key is id so rows with id in new_data should update existing ones in old_data
I need to write a select statement that would give me old_data updated with new data and new data added to it.
Example:
Table a:
id count
1 2
2 19
3 4
Table b:
id count
2 22
5 7
I need a SELECT statement that gives me
id count
1 2
2 22
3 4
5 7
Based on your desired results:
SELECT
*
FROM
[TableB] AS B
UNION ALL
SELECT
*
FROM
[TableA] AS A
WHERE
A.id NOT IN (SELECT id FROM [TableB])
I think this would work pretty neatly with COALESCE:
SELECT a.id, COALESCE(b.count, a.count)
FROM a
FULL OUTER JOIN b
ON a.id = b.id
Note - if your RDBMS does not contain COALESCE, you can write out the function using CASE as follows:
SELECT a.id,
CASE WHEN b.count IS NULL THEN a.count
ELSE b.count END AS count
FROM ...
You can write a FULL OUTER JOIN as follows:
SELECT *
FROM a
LEFT JOIN b
ON a.id = b.id
UNION ALL
SELECT *
FROM b
LEFT a
ON b.id = a.id
You have to use UPSERT to update old data and add new data in Old_data table and select all rows from Old_data. Check following and let me know what you think about this query
UPDATE [old_data]
SET [count] = B.[count]
FROM [old_data] AS A
INNER JOIN [new_Data] AS B
ON A.[id] = B.[id]
INSERT INTO [old_data]
([id]
,[count])
SELECT A.[id]
,A.[count]
FROM [new_Data] AS A
LEFT JOIN [old_data] AS B
ON A.[id] = B.[id]
WHERE B.[id] IS NULL
SELECT *
FROM [old_data]

sql left join and duplicates in result

Say I have 2 tables, A and B, each A entity can possibly have multiple B entities, in one case if I want to get all B's of some certain A's, I might do it with a simple left join
select A.id aid,B.id bid from A
left join B on B.aid = A.id
where A.id = 1
and it will return a result set like
aid bid
1 1
1 2
1 3
As you can see for the first column, all those 1's are kinda duplicates. Is it possible to modify the SQL statement to let him return a result like
aid bid
1 1,2,3
in other words to link all the bid's together as one entity?
Also what if there's another table C, and each A can have multiple C's, how to I make the SQL return a result set like
aid bid cid
1 1,2,3 1,2
instead of
aid bid cid
1 1 1
1 2 1
1 3 1
1 1 2
1 2 2
1 3 2
Thank you very much!
What DBMS are you using?
I can't speak for others, but in MySQL, starting from 4.1, you can use GROUP_CONCAT
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
EG:
select A.id aid, GROUP_CONCAT(DISTINCT B.id) bid from A
left join B on B.aid = A.id
where A.id = 1
GROUP BY a.id
Try using the COALESCE function.
http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string