i have a cros tab query in MS Access which i want to replicate in T-SQL,
T-SQL table '#tmpZSPO_DMD' has Part,Location, Qty,FiscalMonthPeriod. and when i run, the data looks like below.
Part LOCATION Qty FiscalMonthPeriod
123 4040_0086 1 CON00
123 4040_0086 1 CON00
123 4200_0010 1 CON00
123 2070_0060 2 CON01
123 2080_0061 1 CON01
123 4040_0070 1 CON02
123 4040_0070 2 CON02
123 4040_0086 1 CON02
123 2020_0060 2 CON03
123 2020_0064 1 CON03
123 2040_0060 1 CON03
123 4040_0061 1 CON03
123 4040_0061 1 CON03
123 4040_0069 1 CON03
123 4040_0070 1 CON03
I am looking to achieve the below result.
Part LOCATION CON00 CON01 CON02 CON03
123 2020_0060 2
123 2020_0064 1
123 2040_0060 1
123 2070_0060 2
123 2080_0061 1
123 4040_0061 2
123 4040_0069 1
123 4040_0070 3 1
123 4040_0086 2 1
123 4200_0010 1
A very simple PIVOT will do the job.
SELECT *
FROM
(
SELECT Part, LOCATION, Qty, FiscalMonthPeriod
FROM #Table
) t
PIVOT
(
SUM(Qty)
FOR FiscalMonthPeriod IN ([CON00], [CON01], [CON02], [CON03])
) p
Select Part
,LOCATION
,ISNULL(CON00 , 0) AS CON00
,ISNULL(CON01 , 0) AS CON01
,ISNULL(CON02 , 0) AS CON02
,ISNULL(CON03 , 0) AS CON03
FROM tablename T
PIVOT (SUM(Qty)
FOR FiscalMonthPeriod
IN(CON00 , CON01, CON02, CON03)
)p
SELECT tm.PART, tm.Location,
SUM(IIF(tm.FiscalMonthPeriod= 'CON00', [Sum], NULL)) As CON00,
SUM(IIF(tm.FiscalMonthPeriod= 'CON01', [Sum], NULL)) As CON01,
SUM(IIF(tm.FiscalMonthPeriod= 'CON02', [Sum], NULL)) As CON02,
SUM(IIF(tm.FiscalMonthPeriod= 'CON03', [Sum], NULL)) As CON03
FROM #tmpZSPO_DMD tm
GROUP BY tm.PART, tm.Location;
Related
I have a table as follows:
Order_ID
Ship_num
Item_code
Qty_to_pick
Qty_picked
Pick_date
1111
1
1
3000
0
Null
1111
1
2
2995
1965
2021-05-12
1111
2
1
3000
3000
2021-06-24
1111
2
2
1030
0
Null
1111
3
2
1030
1030
2021-08-23
2222
1
3
270
62
2021-03-18
2222
1
4
432
0
Null
2222
2
3
208
0
Null
2222
2
4
432
200
2021-05-21
2222
3
3
208
208
2021-08-23
2222
3
4
232
200
2021-08-25
From this table,
I only want to show the rows that has the latest ship_num information, not the latest pick_date information (I was directed to a question like this that needed to return the rows with the latest entry time, I am not looking for that) for an order i.e., I want it as follows
Order_ID
Ship_num
Item_code
Qty_to_pick
Qty_picked
Pick_date
1111
3
2
1030
1030
2021-08-23
2222
3
3
208
208
2021-08-23
2222
3
4
232
200
2021-08-25
I tried the following query,
select order_id, max(ship_num), item_code, qty_to_pick, qty_picked, pick_date
from table1
group by order_id, item_code, qty_to_pick, qty_picked, pick_date
Any help would be appreciated.
Thanks in advance.
Using max(ship_num) is a good idea, but you should use the analytic version (with an OVER clause).
select *
from
(
select t.*, max(ship_num) over (partition by order_id) as orders_max_ship_num
from table1 t1
) with_max
where ship_num = orders_max_ship_num
order by order_id, item_code;
You can get this using the DENSE_RANK().
Query
;with cte as (
select rnk = dense_rank()
over (Partition by order_id order by ship_num desc)
, *
from table_name
)
Select *
from cte
Where rnk =1;
I tried to run the below query. I want all the data in column rp_num to be in the column rp_num_group. And also i want all the data of the column rp_num which is having count more than one (more than one count in std_id, rp_fam, rn, rp_id) to be in the column std_id_group. But with my query i get the data which is having count more than 1 in both the columns rp_num_group and std_id_group. Kindly suggest the right way to use the joins to get the correct result.
for example, if my table is like below:
std_id rn rp_id rp_fam rp_num
1234 1234 1 abc a12
1234 1235 1 abc a34
1234 1236 1 xyz a56
1244 1246 2 xyz 234
1244 1245 2 hgf z65
1254 1456 2 hgf z78
I would expect my result to be:
std_id rp_num_group std_id_group
1234 a12 a34 a56 a12:abc a34:abc
1244 234 265 z78 z65:hgf z78:hgf
But my result is like below:
std_id rp_num_group std_id_group
1234 a12 a34 a12:abc a34:abc
1244 z65 z78 z65:hgf z78:hgf
SELECT DISTINCT rrpn.std_id,
Stringagg(rrpn.rp_num)
over (
PARTITION BY tmta.rp_id,tmta.rn,tmta.std_id
ORDER BY Nlssort(tmta.mta, 'NLS_SORT=BINARY_CI') ROWS
BETWEEN unbounded
preceding AND unbounded following ) AS rp_num_group,
Stringagg_distinct(rrpn3.rp_num||':'||rrpn3.rp_fam )
over (
PARTITION BY rrpn3.std_id, rrpn3.rn, rrpn3.rp_id
ORDER BY Nlssort(rrpn3.rp_num, 'NLS_SORT=BINARY_CI') ROWS
BETWEEN unbounded
preceding AND unbounded following ) AS std_id_group
FROM data_rrpn rrpn
join data_rrpn rrpn3
ON rrpn3.std_id = rrpn.std_id
AND rrpn3.rp_fam = rrpn.rp_fam
AND rrpn3.rn = rrpn.rn
AND rrpn3.rp_id = rrpn.rp_id
join (SELECT std_id,
rp_fam,
rn,
rp_id,
Count(*)
FROM data_rrpn
GROUP BY std_id,
rp_fam,
rn,
rp_id
HAVING Count(*) > 1) rrpn2
ON rrpn3.std_id = rrpn2.std_id
AND rrpn3.rp_fam = rrpn2.rp_fam
AND rrpn3.rn = rrpn2.rn
AND rrpn3.rp_id = rrpn2.rp_id
ORDER BY rrpn.std_id;
It seems like you want simple string aggregation, with filtering on groups having more than one record:
select
std_id,
listagg(rp_num, ' ') within group(order by rp_num) rp_num_group,
listagg(rp_num || ':' || rp_fam, ' ') within group(order by rp_num) std_id_group
from data_rrpn
group by std_id
having count(*) > 1
You very probably want to to group only on std_id, rp_fam, rp_id and not on RN (which is unique?).
Here you get a preview which rp_nums will be considered (GRP_CNT > 1):
select a.*,
count(*) over (partition by std_id, rp_fam, rp_id) grp_cnt
from tst a;
STD_ID RN RP_ID RP_FA RP_NU GRP_CNT
---------- ---------- ---------- ----- ----- ----------
1234 1234 1 abc a12 2
1234 1235 1 abc a34 2
1234 1236 1 xyz a56 1
1244 1245 2 hgf z65 1
1244 1246 2 xyz 234 1
1254 1456 2 hgf z78 1
The final query would be
with grp as
(
select a.*,
count(*) over (partition by std_id, rp_fam, rp_id) grp_cnt
from tst a
)
select STD_ID,
listagg(RP_NUM, ' ') within group(order by RP_NUM) rp_num_group,
listagg(case when grp_cnt > 1 then RP_NUM || ':' || RP_FAM end, ' ') within group(order by RP_NUM) std_id_group
from grp
group by STD_ID;
giving the result:
STD_ID, RP_NUM_GROUP, STD_ID_GROUP
1234 a12 a34 a56 a12:abc a34:abc
1244 234 z65
1254 z78
Not sur ehow you get the z65:hgf z78:hgfin your sample result, but I think if there is some additional magic logic, you need only adjust the calculation of the GRP_CNT using the analytic function as proposed above.
I have a table that looks like below:
Date User Product
11/15/2019 123 NULL
11/21/2019 123 A
11/21/2019 123 A
11/23/2019 123 B
I want to run a dense_rank function that will skip the null values.
Below is what I currently have:
CASE WHEN PRODUCT IS NOT NULL
THEN DENSE_RANK()
OVER (PARTITION BY USER ORDER BY DATE ASC)
ELSE 1
END DENSE_RANK_OUTPUT
My current output:
Date User Product DENSE_RANK_OUTPUT
11/15/2019 123 NULL 1
11/21/2019 123 A 2
11/21/2019 123 A 2
11/23/2019 123 B 3
My desired output is:
Date User Product DESIRED_OUTPUT
11/15/2019 123 NULL 1
11/21/2019 123 A 1
11/21/2019 123 A 1
11/23/2019 123 B 2
You are close. Just use another key in the partition by:
(CASE WHEN PRODUCT IS NOT NULL
THEN DENSE_RANK() OVER (PARTITION BY USER, (PRODUCT IS NOT NULL) ORDER BY DATE ASC)
ELSE 1
END) as DENSE_RANK_OUTPUT
Feels like it should be simple but my mind has gone blank so would appreciate any help!
Let's say I have this dataset
Date sale_id salesperson Missed_payment_this_month
01/01/2016 1001 John 1
01/01/2016 1002 Bob 0
01/01/2016 1003 Bob 0
01/01/2016 1004 John N/A
01/02/2016 1001 John 1
01/02/2016 1002 Bob 1
01/02/2016 1003 Bob 0
01/02/2016 1004 John 1
01/03/2016 1001 John 1
01/03/2016 1002 Bob 0
01/03/2016 1003 Bob 0
01/03/2016 1004 John 1
And want to add these two columns to the end. They look at the number of missed payments previously, by sales_id and salesperson.
Previous_missed_payment_by_sale_id Previous_missed_payment_by_sales person
0 0
0 0
0 0
0 0
1 1
0 0
0 0
0 1
2 3
1 1
0 1
1 3
sales_id is ok but getting it over sales persons is giving me an error (group by) or adding in extra columns. I need to keep the rows constant.
My best guess that returns extra columns:
select t1.Date, t1.sale_id, t1.salesperson
,sum(case when t2.Missed_payment_this_month = '1' then 1 else 0 end) previous_missed_sales_id
,sum(case when t2.Missed_payment_this_month = '1' then 1 else 0 end) OVER (PARTITION by t1.salesperson) previous_missed_salesperson
from [dbo].[simple_join_table2] t1
inner join [dbo].[simple_join_table2] t2 on
(t2.[Date] < t1.[Date] AND t1.[sale_id] = t2.[sale_id])
group by t1.Date, t1.sale_id, t1.salesperson
,case when t2.Missed_payment_this_month = '1' then 1 else 0 end
this is the output:
Date sale_id salesperson previous_missed_sales_id previous_missed_salesperson
01/02/2016 1002 Bob 0 1
01/02/2016 1003 Bob 0 1
01/03/2016 1002 Bob 0 1
01/03/2016 1002 Bob 1 1
01/03/2016 1003 Bob 0 1
01/02/2016 1001 John 1 3
01/02/2016 1004 John 0 3
01/03/2016 1001 John 2 3
01/03/2016 1004 John 0 3
01/03/2016 1004 John 1 3
Is this possible without another sub query? I guess another way to put it is i'm trying to mimic the sumx and earlier functions of Powerpivot.
If you are on 2012+ use windowing aggregates. Previous = sum all_previous_including_curret - sum current. Ms sql default window is exactly ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
with [simple_join_table2] as(
-- sample data
select cast(valuesDate as Date) valuesDate, sale_id, salesperson, Missed_payment_this_month
from (
values
('20160101',1001,'John', 1)
,('20160101',1002,'Bob ', 0)
,('20160101',1003,'Bob ', 0)
,('20160101',1004,'John',null)
,('20160201',1001,'John', 1)
,('20160201',1002,'Bob ', 1)
,('20160201',1003,'Bob ', 0)
,('20160201',1004,'John', 1)
,('20160301',1001,'John', 1)
,('20160301',1002,'Bob ', 0)
,('20160301',1003,'Bob ', 0)
,('20160301',1004,'John', 1)
) t(valuesDate, sale_id, salesperson, Missed_payment_this_month)
)
select valuesDate,sale_id, salesperson, Missed_payment_this_month,
byidprevmonth = sum(Missed_payment_this_month ) over(partition by sale_id order by valuesDate)
- sum(Missed_payment_this_month) over(partition by valuesDate, sale_id),
bypersonprevmonth = sum(Missed_payment_this_month) over(partition by salesperson order by valuesDate)
- sum(Missed_payment_this_month) over(partition by valuesDate, salesperson)
from [simple_join_table2]
order by salesperson, valuesDate
I have an excel sheet that contains invoices of orders
Each invoice has the following data
ID = a unique id for each ID
CUSTOMER = The name of the ID
AMT = The total value of the invoices
DATE = The date of the purchase
For the following data
CID CUSTOMER AMT DATE
1 James 100 1/1/2012
2 Mark 110 1/1/2012
3 John 110 2/1/2012
1 James 200 2/1/2012
3 John 140 2/1/2012
2 Mark 120 3/1/2012
I need to select records from excel sheet so that i have this output
CID Customer INVCOUNT TotalValue
1 James 2 300
1 John 2 250
1 Mark 2 230
This is the sql i tried
Select
i.[CID],
i.[CUSTOMER],
Count(i.[CID]) as INVCOUNT,
sum(i.AMT) as TotalValue
From
[Invoices] i
Where
i.[DATE] >= #2/1/2012# And
i.[DATE] <= #3/1/2012#
Group By
i.[CID], i.[CUSTOMER]
Having
Count(i.[CID]) > 1
pls this is an excel query, not mysql. The tag i used earlier was a mistake.
WHat am i doing wrong?
To get the output you specified:
Select
1 as CID,
i.[CUSTOMER],
Count(i.[CID]) as INVCOUNT,
sum(i.AMT) as TotalValue
From
[Invoices] i
Where
i.[DATE] >= #1/1/2012# And
i.[DATE] <= #3/1/2012#
Group By
i.[CID], i.[CUSTOMER]
Having
Count(i.[CID]) > 1
To get the output I think you actually want:
Select
i.[CID],
i.[CUSTOMER],
Count(i.[CID]) as INVCOUNT,
sum(i.AMT) as TotalValue
From
[Invoices] i
Where
i.[DATE] >= #1/1/2012# And
i.[DATE] <= #3/1/2012#
Group By
i.[CID], i.[CUSTOMER]
Having
Count(i.[CID]) > 1
This should generate
CID Customer INVCOUNT TotalValue
1 James 2 300
2 John 2 250
3 Mark 2 230