SQL query 'Join' - sql

TABLE A >>
ItemNo Name
1 Item1
2 Item2
3 Item3
4 Item4
TABLE B >>
ItemNo Status
1 available
1 onhold
1 Sold
1 Transit
------------------
2 available
2 onhold
2 Sold
-----------------
3 Transit
-----------------
4 onhold
There are four status on table B onhold,available,sold,Transit
Expected result: if anyone of the itemNo in table B has on either available or Transit,
then I need to get only the table A record of that ItemNo
Output:
Table A:
ItemNo Name
1 Item1
2 Item2
3 Item3
Please advise on how to write MS SQL query for this. Many thanks in advance!

You can solve with a correlated subquery:
SELECT *
FROM tableA ta
WHERE tA.ItemNo IN
(
SELECT tB.ItemNo
FROM tableB tB
WHERE tB.Status in ('available','Transit')
AND tB.ItemNo = ta.ItemNo
)

Join the tables and use SELECT DISTINCT to get just one row from table A.
SELECT DISTINCT a.*
FROM TableA AS a
JOIN TableB AS b ON a.itemNo = b.itemNo
WHERE b.status in ('available', 'Transit')

Related

how to execute query for each row result of another query

I have 2 tables , one stores IDs and another logs for each ID , i would like to get sum of log for each ID and ID number from these 2 tables
A B
------- -------------
ID ID_C LOG
1 1 15
2 1 30
3 4 44
4 2 14
5 3 88
3 10
2 10
for getting sum query is
SELECT SUM(LOG) FROM B WHERE ID_C ='2' ;
notice ID and ID_C are same but name is different in tables
and for getting all ids available query is
SELECT ID FROM A ;
I would like to get the following table result
result
--------------------
ID SUM
1 45
4 44
2 24
3 98
I tried
SELECT SUM(LOG) FROM B WHERE ID_C in (SELECT ID FROM A ) ;
but it result in sum of all IDs
It looks like you just need a join aggregation here:
SELECT a.ID, SUM(b.LOG) AS SUM
FROM A a
INNER JOIN B b
ON b.ID_C = a.ID
GROUP BY a.ID
ORDER BY a.ID;
Note that the inner join will also remove ID values from the A table which no entries whatsoever in the B table, which seems to be the behavior you want.
you should use inner join and GROUP BY:
SELECT A.ID as ID, SUM(LOG) AS SumLOG
FROM A inner join B ON A.ID = B.ID_C
GROUP BY A.ID
if you needed can use where for ID filter.

Combining item and it's category into single column

I'm in need of combining two columns into one in a specific way.
Here are the columns.
Column A (Items) Column B (Category)
Item 1 Category A
Item 2 Category A
Item 3 Category B
Item 4 Category B
Item 5 Category C
Item 6 Category C
...
What i want to achieve is something like this
Column AB
Category A
Item 1
Item 2
Category B
Item 3
Item 4
Category C
Item 5
Item 6
Please advise as i have a feeling that there is a simple resolution for this issue i just can't find it.
Thanks !
Try this
with wt1
as(
select distinct t2.col2 as col1,t2.col2
from tst t2
union all
select t1.col1,t1.col2
from tst t1
)
select col1
from wt1
order by col2,col1;
Output:
COL1
A
item1
item2
B
item3
item4
C
item5
item6
If I understood well, you want all items plus the distinct categories.
The result should be ordered by the category first and then by the item.
You could try something like this:
SELECT ColumnAB
FROM (
SELECT columnB AS Category
columnA AS ColumnAB,
2 AS ColumnType
FROM my_table
UNION ALL
SELECT DISTINCT
columnB AS Category
columnB AS ColumnAB,
1 AS ColumnType
FROM my_table
ORDER BY Category,ColumnType,ColumnAB
)

SQL Join w/ some Math thrown in

Heck, maybe 'joining' isn't even involved. I'm way out of my sql league here. Could someone please help me out w/ the following:
Table A
ItemId ItemLookup Price
------- ---------- -----
1 123456 10.00
2 234567 7.00
3 345678 6.00
Table B
ItemId Location Qty QtyOnHold
------- ---------- ----- ---------
1 1 26 20
2 1 0 0
3 1 12 6
1 2 4 0
2 2 2 1
3 2 16 8
What I'm hoping to get is something that looks like
ItemLookup, Price, (qty minus qtyonhold for loc1), (qty minus qtyonhold for loc2)
or 123456, 10.00, 6, 4
Thank you very much for any direction you can provide.
You can use conditional aggregation and a join:
select a.ItemLookup,
sum(case when Location = 1 then Qty - QtyOnHold end) as Location1,
sum(case when Location = 2 then Qty - QtyOnHold end) as Location2
from tableb b join
tablea a
on b.ItemId = a.ItemId
group by a.ItemLookup;
Somthing like this
select tablea.* ,
(select (qty- QtyOnHold) as qty from tableb where ItemId = tablea.ItemId ans Location = 1 ) as qtyl1,
(select (qty- QtyOnHold) as qty from tableb where ItemId = tablea.ItemId ans Location = 2) as qtyl2
from tablea
This assumes that there's only one row in TableB for each ItemID + Location combination. This is basically just a "pivot", you can learn various ways to do this in MySQL here.
SELECT ItemLookup, Price,
MAX(IF(Location = 1, Qty-QtyOnHold, 0)) avail1,
MAX(IF(Location = 2, Qty-QtyOnHold, 0)) avail2
FROM TableA AS a
JOIN TableB AS b ON a.ItemId = b.ItemId
GROUP BY a.ItemId
It seems to me that it may be possible to have a variable number of locations for each item. If this is the case, you need an aggregate function to convert/concatenate multiple rows into a column.
Here's an example with MySQL's group_concat function:
select a.itemlookup,a.price,group_concat('loc ',location,'=',b.x order by location) as qty_minus_qtyonhold
from tablea a,(select itemid,location,qty-qty_onhold x from tableb
group by itemid,location) as b
where a.itemid = b.itemid
group by 1
You'll get a result like this:
itemlookup price qty_minus_qtyonhold
---------- ------ ------------------
123456 10.00 loc 1=6,loc 2=4
234567 7.00 loc 1=0,loc 2=1
345678 6.00 loc 1=6,loc 2=8
Not sure what DBMS you're using but there are similar alternatives for Oracle and SQL Server

Get the max value of a column from set of rows

I have a table like this
Table A:
Id Count
1 4
1 16
1 8
2 10
2 15
3 18
etc
Table B:
1 sample1.file
2 sample2.file
3 sample3.file
TABLE C:
Count fileNumber
16 1234
4 2345
15 3456
18 4567
and so on...
What I want is this
1 sample1.file 1234
2 sample2.file 3456
3 sample3.file 4567
To get the max value from table A I used
Select MAX (Count) from A where Id='1'
This works well but my problem is when combining data with another table.
When I join Table B and Table A, I need to get the MAX for all Ids and in my query I dont know what Id is.
This is my query
SELECT B.*,C.*
JOIN A on A.Id = B.ID
JOIN C on A.id = B.ID
WHERE (SELECT MAX(COUNT)
FROM A
WHERE Id = <what goes here????>)
To summarise, what I want is Values from Table B, FileNumber from Table c (where the count is Max for ID from table A).
UPDATE: COrrecting table C above. Looks like I need Table A.
I think this is the query you're looking for:
select b.*, c.filenumber from b
join (
select id, max(count) as count from a
group by id
) as NewA on b.id = NewA.id
join c on NewA.count = c.count
However, you should take into account that I don't get why for id=1 in tableA you choose the 16 to match against table C (which is the max) and for id=2 in tableA you choose the 10 to match against table C (which is the min). I assumed you meant the max in both cases.
Edit:
I see you've updated tableA data. The query results in this, given the previous data:
+----+---------------+------------+
| ID | FILENAME | FILENUMBER |
+----+---------------+------------+
| 1 | sample1.file | 1234 |
| 2 | sample2.file | 3456 |
| 3 | sample3.file | 4567 |
+----+---------------+------------+
Here is a working example
Using Mosty’s working example (renaming the keyword count to cnt for a column name), this is another approach:
with abc as (
select
a.id,
a.cnt,
rank() over (
partition by a.id
order by cnt desc
) as rk,
b.filename
from a join b on a.id = b.id
)
select
abc.id, abc.filename, c.filenumber
from abc join c
on c.cnt = abc.cnt
where rk = 1;
select
PreMax.ID,
B.FileName,
C2.FileNumber
from
( select C.id, max( C.count ) maxPerID
from TableC C
group by C.ID
order by C.ID ) PreMax
JOIN TableC C2
on PreMax.ID = C2.ID
AND PreMax.maxPerID = C2.Count
JOIN TableB B
on PreMax.ID = B.ID

SQL query help

Sorry for posting this question again. I rephrased my question a little bit.
I am trying to write a query to return rows from Table-A where multiple rows found in Table-B with STATUS = 1 for each CID column from Table-A.
So in this example CID 100 has two records found in Table-B and STATUS = 1. So I want to write a query to return this row from Table-A. I know this is a weird table design. Please help.
Here are the tables with sample data.
Table-A
-----------------------------------------
AID Name CID
---------------------------------------
10 test1 100
12 test1 100
13 test2 101
14 test2 101
15 test3 102
Table-B
------------------------------------
bID AID status
-----------------------------------
1 10 1
2 12 1
3 14 1
4 15 1
Try this query:
SELECT TableA.CID
FROM TableA
JOIN TableB ON TableA.AID = TableB.AID
WHERE TableB.status = 1
GROUP BY TableA.CID
HAVING COUNT(*) > 1
It returns 100 for your example data.
Something like this?
select aid,
status
from (select aid,
count(*) as cnt
from tableA
group by aid) as aggregated
left join tableB on tableB.aid = aggregated.aid
where aggregated.cnt > 1
If your using SQL:
WITH tableBView AS
(
SELECT AID AS xxxAID
FROM [Table-B]
WHERE status = 1
GROUP BY AID
HAVING COUNT(*) > 0
)
SELECT *
FROM [Table-A]
WHERE EXISTS (SELECT * FROM tableBView WHERE xxxAID = AID)
SELECT *
FROM Table-A a
WHERE a.CID IN
(
SELECT a.CID FROM Table-A a JOIN Table-B b USING (AID)
GROUP BY a.CID
WHERE b.status = 1
HAVING count(*) > 1
)
This is a very verbose way to do it.
Selects all columns from Table-A on rows where AID match between Table-A and Table-B and more than one row with the same CID exists in Table-A:
(Btw, I wouldn't use "-" in your table/column names. Use "_" instead.)
select
derived_table.AID,
derived_table.Name,
derived_table.CID
from
(select
table_A.AID,
table_A.Name,
table_A.CID,
count(table_A.CID) c
from
Table_A
inner join Table_B on (Table_A.AID = table_B.AID)
group by table_A.CID
) derived_table
where
c > 1