Get the max value of a column from set of rows - sql

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

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.

Write Sql script to fetch data in one to many relationship

I want to write a sql script which fetches data from 2 tables one is parent and second is child table
Bid
BidId | Code | Date
1 | H | 2022-05-12
2 | B | 2022-05-13
BidResult
BidResultId | BidId | Emi
12 | 1 | 50
13 | 1 | 20
14 | 2 | 30
Bid and BidResult
i want fetch column Date,Code,BidId from Bid Table
and BidResultId, EMI from BidResult but want a another column of Minimum EMI
from above example i want to fetch for bidId 1
Code H,date 2022-05-12,BidResultId 12, Emi 50 and Min Emi between 50 and 20 which is 20
so i have written following query
Select B.BidId,BR.EMI As Installment,
(Select Min(BR.EMI ) from BidResult BR
Inner Join Bid B on B.BidId = BR.BidResultId
where B.BidId = 5) As MinInstallment,
B.Code,
BR.BidResultId,
CONVERT(DATE, B.Date) As BidDate
from Bid B
Inner Join BidResult BR On B.BidId = BR.BidId
where B.BidId= 5 and B.TypeId = 1
All Field are starightforward except the minimum EMI value from BidResult for that BidId
please check the query and suggest if any modifications
Solution 1: With group by
select BID, min(EMI) EMI
into #temp
from BIDResult
group by BID
select b.Date, b.Code, b.BidId, br.BidResultId, br.EMI
from BID b
inner join #temp on t.BID = b.BID
inner join BIDResult br on br.BID = t.BID and br.EMI = t.EMI
Solution 2: Without group by
select *, ROW_Number() over(PARTITION by BID order by EMI) RowNumber
into #temp
from BIDResult
select b.Date, b.Code, b.BidId, br.BidResultId, br.EMI
from BID b
inner join #temp t on t.BID = b.BID and t.RowNumber = 1

How to identify non-existing keys with reference to a table that has all mandatory keys, SQL?

I have the table 'Table01' which contains the keys that should be mandatory:
id
1
2
3
4
And I also have the table 'Table02' which contains the records to be filtered:
id
customer
weight
1
a
100
2
a
300
3
a
200
4
a
45
1
b
20
2
b
100
3
b
17
1
c
80
4
c
90
2
d
30
3
d
30
4
d
50
So I want to identify which are the mandatory id's that the table 'Table02' does not have, and in turn identify which is the 'customer' of each id's that the table 'Table02' does not have.
The resulting table should look like this:
customer
id
b
4
c
2
c
3
d
1
What I have tried so far is a 'rigth join'.
proc sql;
create table table03 as
select
b.id
from table02 a
right join table01 b
on a.id=b.id
where a.id is null;
run;
But that query is not identifying all the id's that should be mandatory.
I hope someone can help me, thank you very much.
here is one way:
select cl.customerid , a.id
from
Table1 a
cross join
( select customerid
from table2
group by customerid
) cl
where not exists ( select 1 from table2 b
where b.customerid = cl.customerid
and b.id = a.id
)
You can use an EXCEPT between two sub-selects. The first creates a matrix of all possibilities, and the except table is a selection of the extant customers.
Example:
data ids;
do id = 1 to 4; output; end;
run;
data have;
input id customer $ weight;
datalines;
1 a 100
2 a 300
3 a 200
4 a 45
1 b 20
2 b 100
3 b 17
1 c 80
4 c 90
2 d 30
3 d 30
4 d 50
run;
proc sql;
create table want(label='Customers missing some ids') as
select matrix.*
from
(select distinct have.customer, ids.id from have, ids) as matrix
except
(select customer, id from have)
;
quit;
If you are doing it in SQL server. Something like #eshirvana above posted, but also you can use with cte:
;with cte as
(
SELECT t1.id, t2.Customer
FROM Table01 t1
cross join (select distinct customer from Table02)
)
SELECT a.customer, a.id FROM cte a
LEFT JOIN Table02 b
ON a.id=b.id AND a.customer=b.customer
where b.id is null

How to join only latest date values from another table and prevent duplication

I'm trying to lookup a unique value from table b and get it into table a.
Table b stores multiple values that are changing by date.
I would like to join but only getting the values with the latest date from table b.
Table a
Unique ID
1
2
Table b
Date Unique ID Price
01/01/2019 1 100
01/02/2019 1 101
01/03/2019 1 102
01/01/2019 2 90
01/02/2019 2 91
01/03/2019 2 92
Expected result
Unique ID Price Date
1 102 01/03/2019
2 92 01/03/2019
Appreciate your help!
Have a sub-query that returns each UniqueID together with its max date. IN that result.
select * from tablename
where (UniqueID, date) in (select UniqueID, max(date)
from tablename
group by UniqueID)
You want correlated subquery :
select b.*
from tableb b
where b.date = (select max(b1.date) from tableb b1 where b1.UniqueID = b.UniqueID);
If you want to go with JOIN then you can do JOIN with subquery :
select a.UniqueID , b.Price, b.Date
from tablea a inner join
tableb b
on b.UniqueID = a.UniqueID
where b.date = (select max(b1.date) from tableb b1 where b1.UniqueID = a.UniqueID);
A correlated subquery?
select b.*
from b
where b.date = (select max(b2.date) from b b2 where b2.unique_id = b.unique_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