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
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.
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
)
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
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
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