How to SUM many rows into 1 row in SQL Server? - sql

The following is my syntax
with AA as
(
select distinct Store_Code, sum([Transactions]) as totaltrans
from CRM_RETAIL_SUMMARY
where Store_Code in ('L43','J62','L45','UA2','A35','949','C50','L44','Y45')
and Trans_Hdr_Sale_Date BETWEEN '2018-12-1' AND '2018-12-31'
group by Transactions, Store_Code
),
BB as
(
select distinct[Store_Code] as storecode from CRM_RETAIL_SUMMARY
)
select AA.totaltrans, BB.storecode
from AA
inner join BB on AA.Store_Code = BB.storecode
and then the result shows this:
storecode totaltrans
----------------------
A35 65
A35 76
A35 48
A35 62
A35 56
UA2 5
UA2 6
UA2 8
UA2 15
UA2 9
UA2 16
949 16
949 29
949 55
But I want to SUM each of the storecode like the following but I don't know how:
storecode totaltrans
---------------------
A35 307
UA2 59
Thank you for all answers

You only need to group by store_code, not store_code, transactions. and you don't need the 2nd cte.
with AA as (
select Store_Code, sum([Transactions]) as totaltrans
from CRM_RETAIL_SUMMARY
where Store_Code in ('L43','J62','L45','UA2','A35','949','C50','L44','Y45')
and Trans_Hdr_Sale_Date BETWEEN '2018-12-1' AND '2018-12-31'
group by Store_Code
)
select * from AA;

Would you just use group by?
select BB.storecode, sum(AA.totaltrans)
from AA join
BB
on AA.Store_Code = BB.storecode
group by BB.storecode;
Of course, this goes after the CTEs.

Related

Get only latest records of each ID in PostgreSQL

I have two tables
accounts table
account_id location_id
1 11
1 12
2 21
2 22
Events_table
location_id events_id event_date
11 e1 2022/03/04
11 e3 2022/03/05
12 e2 2022/03/10
21 e5 2022/04/10
21 e2 2022/04/09
The result I expected is to get only latest event_id for location with respect to account
Result Expected:
account_id location_id events_id event_date
1 11 e3 2022/03/05
1 12 e2 2022/03/10
2 21 e5 2022/04/10
Use:
with cte as
( select *,
row_number() over(partition by location_id order by event_date desc ) row_num
from Events
) select a.account_id,
a.location_id,
cte.events_id,
cte.event_date
from accounts a
inner join cte on cte.location_id=a.location_id
where cte.row_num=1;
Demo

duplicate values in DB2

I am working on DB2.
There are duplicate rows in the table. I need to extract data where there is different value in 2nd column for same value in 1st column.
there are column other than these in table but only need to consider these.
for example:
NBR
SE_NBR
123
56
123
56
123
56
248
75
248
75
To extract
NBR
SE_NBR
456
12
456
34
456
11
135
77
135
88
here is one way using window function:
select * from
(
select *, min(SE_NBR) over (partition by NBR) minnbr, max(SE_NBR) over (partition by NBR) maxnbr
from nbrtable
) t
where minnbr <> maxnbr
if window function is not supported:
select * from tableName t1
where exists (
select 1 from tablename t2
where t1.NBR = t2.NBR
group by t2.nbr
having count(distinct SE_NBR) > 1
)
db<>fiddle here
You can do:
select *
from t
where nbr in (
select nbr from t group by nbr having count(distinct se_nbr) > 1
)

Removing pairs of transactions

I am attempting to remove transactions that have been reversed from a table. the table has Account, Date, Amount and Row. If a transaction has been reversed Account will match and Amount will be inverse of each other.
Example Table
Account Date Amount Row
12 1/1/18 45 72 -- Case 1
12 1/2/18 50 73
12 1/2/18 -50 74
12 1/3/18 52 75
15 1/1/18 51 76 -- Case 2
15 1/2/18 51 77
15 1/2/18 -51 78
15 1/2/18 51 79
18 1/2/18 50 80 -- Case 3
18 1/2/18 50 81
18 1/2/18 -50 82
18 1/2/18 -50 83
18 1/3/18 50 84
18 1/3/18 50 85
20 1/1/18 57 88 -- Case 4
20 1/2/18 57 89
20 1/4/18 -57 90
20 1/5/18 57 91
Desired Results Table
Account Date Amount Row
12 1/1/18 45 72 -- Case 1
12 1/3/18 52 75
15 1/1/18 51 76 -- Case 2
15 1/2/18 51 79
18 1/3/18 50 84 -- Case 3
18 1/3/18 50 85
20 1/1/18 57 88 -- Case 4
20 1/5/18 57 91
Removing all instances of inverse transactions does not work when there are multiple transactions when all other columns are the same. My attempt was to count all duplicate transactions, count of all inverse duplicate transactions, subtracting those to get the number of rows I needed from each transactions group. I was going to pull the first X rows but found in most cases I want the last X rows of each group, or even a mix (the first and last in Case 2).
I either need a method of removing pairs from the original table, or working from what I have so far, a method of distinguishing which transactions to pull.
Code so far:
--adding row Numbers
with a as (
select
account a,
date d,
amount f,
row_number() over(order by account, date) r
from table),
--counting Duplicates
b as (
select a.a, a.f, Dups
from a join (
select a, f, count(*) Dups
from a
group by a.a, a.f
having count(*)>1
) b
on a.a=b.a and
b.f=a.f
where a.f>0
),
--counting inverse duplicates
c as (
select a.a, a.f, InvDups
from a join (
select a, f, count(*) InvDups
from a
group by a.a, a.f
having count(*)>1
) b
on a.a=b.a and
-b.f=a.f
where a.f>0
),
--combining c and d to get desired number of rows of each transaction group
d as (
select
b.a, b.f, dups, InvDups, Dups-InvDups TotalDups
from b join c
on b.a=c.a and
b.f=c.f
),
--getting the number of rows from the beginning of each transaction group
select d.a, d.d, d.f
from
(select
a, d, f, row_number() over (group by a, d, f) r2
from a) e
join d
on e.a=d.a and
TotalDups<=r2
You can try this.
SELECT T_P.* FROM
( SELECT *, ROW_NUMBER() OVER(PARTITION BY Account, Amount ORDER BY [Row] ) RN from #MyTable WHere Amount > 0 ) T_P
LEFT JOIN
( SELECT *, ROW_NUMBER() OVER(PARTITION BY Account, Amount ORDER BY [Row] ) RN from #MyTable WHere Amount < 0 ) T_N
ON T_P.Account = T_N.Account
AND T_P.Amount = ABS(T_N.Amount)
AND T_P.RN = T_N.RN
WHERE
T_N.Account IS NULL
The following handles your three cases:
with t as (
select t.*,
row_number() over (partition by account, date, amount order by row) as seqnum
from table t
)
select t.*
from t
where not exists (select 1
from t t2
where t2.account = t.account and t2.date = t.date and
t2.amount = -t.amount and t2.seqnum = t.seqnum
);
Use This
;WITH CTE
AS
(
SELECT
[Row]
FROM YourTable YT
WHERE Amount > 0
AND EXISTS
(
SELECT 1 FROM YourTable WHERE Account = YT.Account
AND [Date] = YT.[Date]
AND (Amount+YT.Amount)=0
)
UNION ALL
SELECT
[Row]
FROM YourTable YT
WHERE Amount < 0
AND EXISTS
(
SELECT 1 FROM YourTable WHERE Account = YT.Account
AND [Date] = YT.[Date]
AND (Amount+YT.Amount)>0
)
)
SELECT * FROM YourTable
WHERE EXISTS
(
SELECT 1 FROM CTE WHERE [Row] = YourTable.[Row]
)

Select distinct from user_id with minimum date and all rest user fields using sql

let's say I have a table:
USER_ID DATE EXT_DATA1 EXT_DATA2 EXT_DATA3 EXT_DATA4 EXT_DATA5
11 031213 77 aa bb cc dd
11 031213 77 aa bb cc dd
11 041213 77 aa bb1 cc dd1
11 051213 78 aa bb2 cc1 dd2
12 040313 79 aa bb4 cc dd
I tried to get unique user_id with MIN date and all rest fields:
SELECT MIN(DATE) AS ACTUAL_DATE,USER_ID,EXT_DATA1,EXT_DATA2,EXT_DATA3,EXT_DATA4,EXT_DATA5 /
GROUP BY EXT_DATA1,EXT_DATA2,EXT_DATA3,EXT_DATA4,EXT_DATA5 ;
but because I have different values in columns EXT_DATA1 ,EXT_DATA2 and etc
I get duplicates in final results :
USER_ID DATE EXT_DATA1 EXT_DATA2 EXT_DATA3 EXT_DATA4 EXT_DATA5
11 041213 77 aa bb1 cc dd1
11 051213 78 aa bb2 cc1 dd2
12 040313 79 aa bb4 cc dd
Edited to fix mistake in description
This should give you the result you are looking for:
SELECT t1.USER_ID,
t1.DATE,
t1.EXT_DATA1,
t1.EXT_DATA2,
t1.EXT_DATA3,
t1.EXT_DATA4,
t1.EXT_DATA5
FROM Table1 t1
LEFT JOIN Table1 t2 ON t1.USER_ID = t2.USER_ID
AND t1.DATE > t2.DATE
WHERE t2.USER_ID IS NULL
sqlfiddle demo
Note: This may return more than one row for each user_id if the smallest date is present in multiple rows.
Will it do the work :
SELECT ACTUAL_DATE,USER_ID,EXT_DATA1,EXT_DATA2,EXT_DATA3,EXT_DATA4,EXT_DATA5
FROM
(
SELECT "DATE" AS ACTUAL_DATE,
USER_ID,EXT_DATA1,EXT_DATA2,EXT_DATA3,EXT_DATA4,EXT_DATA5,
ROW_NUMBER() OVER(PARTITION BY USER_ID ORDER BY "DATE" ) as rn
FROM table_name
)a
WHERE rn = 1;
UPDATE
Since DATE is a keyword in Oracle, it needs escaping (with double quotes). Query uses analytic (or windowing) function ROW_NUMBER to get the first row (sorted by date) for each user

Pivot SQL with Rank

Basically i have the following query and i am trying to distinguish only the unique ranks from this:
WITH numbered_rows
as (
SELECT Claim,
reserve,
time,
RANK() OVER (PARTITION BY ClaimNumber ORDER BY time asc) as 'Rank'
FROM (
SELECT cc.Claim,
MAX(csd.time) as time,
csd.reserve
FROM ClaimData csd WITH (NOLOCK)
JOIN Core cc WITH (NOLOCK)
on cc.ClaimID = csd.ClaimID
GROUP BY cc.Claim, csd.Reserve
) as t
)
select *
from numbered_rows cur, numbered_rows prev
where cur.Claim= prev.Claim
and cur.Rank = prev.Rank -1
The results set I get is the following:
Claim reserve Time Rank Claim reserve Time Rank
--------------------------------------------------------------------
11 0 12/10/2012 1 11 15000 5/30/2013 2
34 2000 1/21/2013 1 34 750 1/31/2013 2
34 750 1/31/2013 2 34 0 3/31/2013 3
07 800000 5/9/2013 1 07 0 5/10/2013 2
But what I only want to see the following: (have the Claim 34 Rank 2 removed because its not the highest
Claim reserve Time Rank Claim reserve Time Rank
--------------------------------------------------------------------
11 0 12/10/2012 1 11 15000 5/30/2013 2
34 750 1/31/2013 2 34 0 3/31/2013 3
07 800000 5/9/2013 1 07 0 5/10/2013 2
I think you can do this by just reversing your logic, i.e. order by time DESC, switching cur and prev in your final select and changing -1 to +1 in your final select, then just limiting prev.rank to 1, therefore ensuring that the you only include the latest 2 results for each claim:
WITH numbered_rows AS
( SELECT Claim,
reserve,
time,
[Rank] = RANK() OVER (PARTITION BY ClaimNumber ORDER BY time DESC)
FROM ( SELECT cc.Claim,
[Time] = MAX(csd.time),
csd.reserve
FROM ClaimData AS csd WITH (NOLOCK)
INNER JOIN JOIN Core AS cc WITH (NOLOCK)
ON cc.ClaimID = csd.ClaimID
GROUP BY cc.Claim, csd.Reserve
) t
)
SELECT *
FROM numbered_rows AS prev
INNER JOIN numbered_rows AS cur
ON cur.Claim= prev.Claim
AND cur.Rank = prev.Rank + 1
WHERE prev.Rank = 1;