sql top 1 based on group records - sql

Table ProductMst (combination is unique - CodeNum, MainCatid, SubCatid)
id CodeNum MainCatid SubCatid Desc Qty
1 001 1 1 prod1 5
2 001 1 2 prod2 10
3 001 2 3 prod3 1
4 002 2 3 prod4 2
5 003 2 3 prod5 3
6 004 1 1 prod6 4
Sub Table SubCatMst
id name subcode
1 scat1 00
2 scat2 00
3 scat3 02
4 scat4 03
Desired Result
id CodeNum MainCatid SubCatid Desc Qty subcode
2 001 1 2 prod2 15 00
3 001 2 3 prod3 1 02
4 002 2 3 prod4 2 02
5 003 2 3 prod5 3 02
6 004 1 1 prod6 4 00
Basically, i wanted to group subcode if same and sum (Qty) based on subcode. And, take the TOP 1 records data as all columns based on MAX(Qty).
Summary: Please check first 2 records which combines.
Query Attempt:
select * from (
select A.*, B.subcode,
ROW_NUMBER() OVER( PARTITION BY A.CodeNum, A.MainCatid, B.subcode ORDER BY A.Qty desc) as row
from ProductMst A
inner join SubCatMst B on A.SubCatid=B.id
) as A where row<=1

Your question says:
i wanted to group subcode if same
If what is the same? I assume this means if codenum is the same.
Regardless of the exact field(s), the logic is the same. You can use window functions to aggregate the data and determine the row to choose:
select ps.*
from (select p.*, sc.subcode,
sum(qty) over (partition by codenum, subcode) as qty,
row_number() over (partition by codenum, subcode order by qty desc) as seqnum
from ProductMst p join
SubCatMst sc
on p.subcatid = sc.id
) ps
where seqnum = 1;

Related

Count record with condition other table and multiple table

need help from expert here....I need to count record where condition specific customerID based on hm_value
Here is my table named risk
logNo customerID
r1 001
r2 002
r3 001
r4 001
Table named riskMov where the relation of risk.logNo and riskMov.logNo is 1:M
Need to take one record from multiple id where latest date
logNo hm_value date_created
r1 11 2021-01-21
r1 12 2021-03-03
r2 14 2021-02-21
r3 13 2021-02-22
r3 12 2021-04-22
r4 13 2021-01-21
Customer table where the relation customer.customerID and risk.CustomerID 1:M
customerID custName
001 Oppo
002 Samsung
003 Nokia
004 Motorola
005 Huawei
HeatMap Table where the relation Heatmap.value and RiskMov.hm_value m:1
xAxis yAxis value
1 1 11
2 1 12
3 1 13
4 1 14
5 1 15
I need return all count from table risk record where specific customerID condition .
I try use case when user customerId = '001' then null with multiple join of table but not expected result
Here is my attempt query
SELECT d."yaxis" AS y,
d."xaxis" AS x,
CASE
WHEN c."customerid" = '001' THEN ( Count(DISTINCT a.customerid) )
ELSE 0
END AS count
FROM PUBLIC."risk" a
INNER JOIN (SELECT DISTINCT logno,
hm_value
FROM PUBLIC."riskmov") b
ON a.logno = b.logno
RIGHT JOIN PUBLIC."customer" c
ON c.customerid = b."customerid"
RIGHT JOIN PUBLIC."heatmap" d
ON b."value" = d."value"
GROUP BY d."yaxis",
d."axis",
c."cu_customer_id"
ORDER BY d."yaxis",
d."xaxis" DESC
My expected result as below
xAxis yAxis count(count record by specfic customer. eg- customerID = '001')
1 1 1
2 1 1
3 1 1
4 1 0
5 1 0

Get TOP 1 row from multiple tables based on date

I have five tables in a SQL Server database. These tables are listed below and I want to select Data from these tables according to date. I tried searching but could not find solution for multiple tables. Please help
TABLE1
id PId CId
----------- ---------- ------------
1 P001 1
2 P002 2
3 P003 4
4 P004 5
TABLE2
id CId CNo ConId
----------- ---------- ------------ ----------
1 1 1 C123
2 1 2 PA444
3 1 3 PA456
4 2 1 AUX2398
5 2 2 AUX2345
6 4 1 PA123
7 5 1 C234
TABLE3
id CId CNo Label Date
----------- ---------- ------------ ---------- ----------
1 1 1 A 1/1/2000
2 1 2 A 15/10/2020
3 1 3 A 20/10/2020
4 2 1 A 15/10/2020
5 2 2 A 20/10/2020
6 4 1 A 20/10/2020
7 5 1 A 27/10/2020
TABLE4
id CId CNo Label Date
----------- ---------- ------------ ---------- ----------
1 1 1 B 20/10/2020
2 1 2 B 27/10/2020
3 1 3 B 22/10/2020
4 2 1 B 22/10/2020
5 2 2 B 26/10/2020
6 4 1 B 22/10/2020
7 5 1 B 30/10/2020
TABLE5
id CId CNo Label Date
----------- ---------- ------------ ---------- ----------
1 1 1 C 26/10/2020
2 1 2 C 1/1/2000
3 1 3 C 23/10/2020
4 2 1 C 25/10/2020
5 2 2 C 30/10/2020
6 4 1 C 25/10/2020
7 5 1 C 1/1/2000
I want to select Label and Date from Table 3, 4 and 5 where Date is >1/1/2000 and < than and close to 24/10/2020 and grouped according to PId, CId, ConId and CNo.
Desired result:
PId CId ConId CNo Label Date
-------- ---------- ---------- -------- --------- ----------
P001 1 C123 1 B 20/10/2020
P001 1 PA444 2 A 15/10/2020
P001 1 PA456 3 C 23/10/2020
P002 2 AUX2398 1 B 22/10/2020
P002 2 AUX2345 2 A 20/10/2020
P003 4 PA123 1 B 22/10/2020
P004 5 C234 1 - -
Any help will be appreciated. Thank you.
You can achieve this with a couple of CTE's; the first forms a UNION of TABLE3, TABLE4 and TABLE5; the second generates a row number based on the Date descending for each partition of PId, CId, ConId and CNo. We then select all rows from the second CTE where the row number is 1:
WITH CTE AS (
SELECT * FROM Table3 WHERE date > '2000-01-01'
UNION ALL
SELECT * FROM Table4 WHERE date > '2000-01-01'
UNION ALL
SELECT * FROM Table5 WHERE date > '2000-01-01'
),
CTE2 AS (
SELECT t1.PId, t1.CId, t2.ConId, t2.CNo, CTE.Label, CTE.Date,
ROW_NUMBER() OVER (PARTITION BY t1.PId, t1.CId, t2.ConId, t2.CNo ORDER BY CTE.Date DESC) AS rn
FROM TABLE1 t1
JOIN TABLE2 t2 ON t2.CId = t1.CId
LEFT JOIN CTE ON CTE.Cid = t2.CId AND CTE.CNo = t2.CNo AND CTE.Date < '2020-10-24'
)
SELECT PId, CId, ConId, CNo, Label, Date
FROM CTE2
WHERE rn = 1
ORDER BY PId, CId, CNo
Output:
PId CId ConId CNo Label Date
P001 1 C123 1 B 2020-10-20
P001 1 PA444 2 A 2020-10-15
P001 1 PA456 3 C 2020-10-23
P002 2 AUX2398 1 B 2020-10-22
P002 2 AUX2345 2 A 2020-10-20
P003 4 PA123 1 B 2020-10-22
P004 5 C234 1 - -
Demo on dbfiddle

Issue with SQL Group By and COALESCE on sqlite

I have a table as below in sqlite database. I want to create a line chart showing usage by product groups.
Table: ProductUsageData
UserID ProductName ProductGroup Qty RecordID
1 A1 A 12 1
2 A1 A 12 1
1 A2 A 15 1
3 A1 A 12 2
2 B1 B 12 2
5 B2 B 5 2
1 A1 A 12 3
1 A2 A 15 3
4 A1 A 12 3
3 C1 C 12 3
2 C2 C 15 3
Since I want separate line for each ProductGroup I am using below Query
SELECT
SUM(Qty) as UsedQty,
ProductGroup,
RecordID
FROM ProductUsageData
GROUP BY ProductGroup, RecordID
ORDER BY RecordID ASC;
While I get three records for A (for each RecordID) I get only 1 record each for B & C as they are not used during each RecordID.
Problem is when I am putting one line for each ProductGroup in the chart, the points for B & C are shown as per Qty in the first
My output is like this
A 39 1
A 12 2
B 17 2
A 39 3
C 27 3
So the graph looks like this
instead of
To fix this I changed the query using COALESCE to get 0 Qty if the ProductGroup is not used during each recording.
SELECT
COALESCE(SUM(Qty), 0) as UsedQty,
ProductGroup,
RecordID
FROM ProductUsageData
GROUP BY ProductGroup, RecordID
ORDER BY RecordID ASC;
I was expecting output as below
A 39 1
B 0 1
C 0 1
A 12 2
B 17 2
C 0 2
A 39 3
B 0 3
C 27 3
But I am getting same output as first
Please let me know how can I correct the query to get desired output
A typical solution is to first cross join two queries that select the distinct product groups and record ids from the table; this gives you all possible combinations of productGroup and recordID.
Then, you can bring in the original table with a left join, and aggregate:
select
g.productGroup,
coalesce(sum(p.qty), 0) qty,
r.recordID
from (select distinct productGroup from productUsageData) g
cross join (select distinct recordID from productUsageData) r
left join productUsageData p
on p.productGroup = g.productGroup
and p.recordID = r.recordID
group by r.recordID, g.productGroup
order by r.recordID, g.productGroup
In the real world, you might have separate referential tables for product groups and records ids, which would make the query simpler and more efficient (since it would avoid the need to select distinct in subqueries).
Demo on DB Fiddle:
productGroup | qty | recordID
:----------- | :-- | :-------
A | 39 | 1
B | 0 | 1
C | 0 | 1
A | 12 | 2
B | 17 | 2
C | 0 | 2
A | 39 | 3
B | 0 | 3
C | 27 | 3

Edit 2 rows into 2 columns in a single result SQL

I have the following table:
WorkID WorkDesc
--------------------
1 ABCD
2 DEFG
3 HIJK
then I've the following table as the detail of table one:
WorkDetailID WorkID WorkDetailDesc
-----------------------------------------
1 1 001
2 1 002
3 2 006
4 2 007
5 3 015
Each WorkID is always have maximum 2 records and minimum is 1.
I want to have the following result:
WorkID WorkDesc WorkDetailID1 WorkDetailID2
-------------------------------------------------------
1 ABCD 1 2
2 DEFG 3 4
3 HIJK 5 null
Does anyone have an idea how to do that?
Thank you.
You can use pivot. I prefer conditional aggregation. In either case, you need a column for the pivoting. row_number() to the rescue:
select t1.workid, t1.workdesc,
max(case when t2.seqnum = 1 then t2.workdetailid end) as workdetailid1,
max(case when t2.seqnum = 2 then t2.workdetailid end) as workdetailid2
from t1 join
(select t2.*,
row_number() over (partition by t2.workid order by t2.workdetailid) as seqnum
from t2
) t2
on t1.workid = t2.workid
group by t1.workid, t1.workdesc

Queries to fetch items based on top Ranks

I have a table which rank the items which i have.
I need a queries which will pick up only the top 2 ranks for a given item, the rank may not be in sequential order.
I need to fetch the item with least two ranks, there will same rank for two items as well.
Here is the snap shot of my table.
Item Id Supp Id Rank
1 2 2
1 1 7
1 7 5
1 9 11
2 67 4
2 9 14
2 10 14
2 34 4
2 25 3
2 60 3
2 79 5
my requirement is if I enter 2 i should get the result as below
Item Id Supp_id Rank
2 25 3
2 60 3
2 67 4
2 34 4
I am using oracle 10g version.
As one of the approaches it can be done as follows. Here we are using dense_rank() over() analytic function to assign a rank for a row in a ordered by rank group of rows .
select t.item_id
, t.supp_id
, t.rank
from (select item_id
, supp_id
, rank
, dense_rank() over(partition by item_id
order by rank) as rn
from t1
where item_id = 2
) t
where t.rn <= 2
Result:
ITEM_ID SUPP_ID RANK
---------- ---------- ----------
2 25 3
2 60 3
2 67 4
2 34 4
SQLFiddle Demo