How to Unpivot with multiple column - sql

Below is my table structure. i wants to unpivot below data.
amount user amount1 user1 amount2 user2 amount3 user3 amount4 user4
10 1 20 2 30 3 40 4 50 5
Now i wants result as below.
amount user
10 1
20 2
30 3
40 4
50 5

You want to unpivot the data. I recommend apply:
select v.*
from t cross apply
(values (t.amount, t.user),
(t.amount1, t.user1),
(t.amount2, t.user2),
(t.amount3, t.user3),
(t.amount4, t.user4)
) v(amount, user);

You can try the following it will work for your specific case here:
SELECT 'user' + CAST(ROW_NUMBER() OVER(partition BY 1 ORDER BY amountx) AS VARCHAR) AS [user],amountx
FROM [table]
UNPIVOT(
amountx
FOR amntx IN (amount,amount1,amount2,amount3,amount4)
) AS UP
http://rextester.com/EWXV86982

Related

SUM a column in SQL, based on DISTINCT values in another column, GROUP BY a third column

I'd appreciate some help on the following SQL problem:
I have a table of 3 columns:
ID Group Value
1 1 5
1 1 5
1 2 10
1 2 10
1 3 20
2 1 5
2 1 5
2 1 5
2 2 10
2 2 10
3 1 5
3 2 10
3 2 10
3 2 10
3 4 50
I need to group by ID, and I would like to SUM the values based on DISTINCT values in Group. So the value for a group is only accounted for once even though it may appear multiple for times for a particular ID.
So for IDs 1, 2 and 3, it should return 35, 15 and 65, respectively.
ID SUM
1 35
2 15
3 65
Note that each Group doesn't necessarily have a unique value
Thanks
the CTE will remove all duplicates, so if there a sdiffrenet values for ID and Group, it will be counted.
The next SELECT wil "GROUP By" ID
For Pstgres you would get
WITH CTE as
(SELECT DISTINCT "ID", "Group", "Value" FROM tablA
)
SELECT "ID", SUM("Value") FROM CTE GROUP BY "ID"
ORDER BY "ID"
ID | sum
-: | --:
1 | 35
2 | 15
3 | 65
db<>fiddle here
Given what we know at the moment this is what I'm thinking...
The CTE/Inline view eliminate duplicates before the sum occurs.
WITH CTE AS (SELECT DISTINCT ID, Group, Value FROM TableName)
SELECT ID, Sum(Value)
FROM CTE
GROUP BY ID
or
SELECT ID, Sum(Value)
FROM (SELECT DISTINCT * FROM TableName) CTE
GROUP BY ID

How to pivot on 2 fields

Here is the table I have:
PeriodID RecordID Basis Amount1 Amount2
1 1 IFRS 10 100
1 2 IFRS 20 200
2 1 IFRS 15 150
2 2 IFRS 25 250
1 1 CGAAP 30 300
1 2 CGAAP 40 400
2 1 CGAAP 35 350
2 2 CGAAP 45 450
I would like to pivot on the PeriodID and Basis field so that the result would have following columns:
RecordID
Period1IFRSAmount1
Period2IFRSAmount1
PeriodID1IFRSAmount2
PeriodID2IFRSAmount2
Period1CGAAPAmount1
Period2CGAAPAmount1
PeriodID1CGAAPAmount2
PeriodID2IFRSAmount22
First of all, you need to create the ouput that you need as rows. That is why union part is really important. After you construct your data you can easily use PIVOT.
Following query written in SQL SERVER. It should be similar to other databases as well.
SELECT *
FROM
(
SELECT RecordID, 'Period' + CONVERT(VARCHAR, PeriodID) + Basis + 'Amount1' AS Basis, Amount1 AS Amount
FROM TableName
UNION ALL
SELECT RecordID, 'Period' + CONVERT(VARCHAR, PeriodID) + Basis + 'Amount2' AS Basis, Amount2 AS AMOUNT
FROM TableName
) AS Q
PIVOT (
SUM(Amount)
FOR Basis IN
(
[Period1IFRSAmount1],
[Period2IFRSAmount1],
[Period1IFRSAmount2],
[Period2IFRSAmount2],
[Period1CGAAPAmount1],
[Period2CGAAPAmount1],
[Period1CGAAPAmount2],
[Period2CGAAPAmount2]
)
) AS P

How to get minimum date by group id per client id

I am trying to Select Group ID, and minimum dates per clients ID.
This is sample data set.
ClientID GroupID DataDate
1 9 2016-05-01
2 8 2015-04-01
3 7 2016-07-05
1 6 2015-01-05
1 5 2014-11-12
2 4 2016-11-02
1 3 2013-02-14
2 2 2011-04-01
I wrote
SELECT
clientID, MIN(DataDate)
FROM sampleTable
GROUP BY clientID
But in this query, I do not have GroupID selected. I need to include GroupID to join another table.
If I do:
Select
ClientID, GroupID, MIN(DataDate)
FROM sampleTable
GROUP BY ClientID, GroupID
It won't really get minimum dates per client.
Could you help me. How I should do this?
You can use ROW_NUMBER instead:
SELECT
ClientID, GroupID, DataDate
FROM (
SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY ClientID ORDER BY DataDate)
FROM SampleData
) t
WHERE rn = 1
If you want to include ties, use RANK instead of ROW_NUMBER.
I hope i understood your question correctly .
You want to display min dates for each client id's
If my table has data like this:
CID GID D1
1 9 03-06-2016
1 6 01-06-2017
1 5 01-06-2015
1 3 01-06-2014
2 4 01-06-2017
2 8 01-06-2014
3 5 03-06-2016
2 4 01-06-2011
Output :
CID GID D1
1 3 01-06-2014
2 4 01-06-2011
3 5 03-06-2016
This is what i think you can go with .
select cx.cid,cx.gid, cx.d1 from cli cx where cx.d1=(select min(c1.d1) from cli c1 where c1.cid=cx.cid)
group by cx.cid,cx.gid,cx.d1
order by cx.gid
Hope it helps.

Assigning a value of data for each record having the same condition in SQL Server 2008

I have a table in SQL Server 2008 like:
Period Name Value
1 A 10
2 A 20
3 A 30
4 A 40
1 B 50
2 B 80
3 B 70
4 B 60
What I need to write a select query includes a new column MainValue which contains the value where period=4 for a name for each data.
Example:
Period Name Value MainValue
1 A 10 40
2 A 20 40
3 A 30 40
4 A 40 40
1 B 50 60
2 B 80 60
3 B 70 60
4 B 60 60
How can I provide this? I tried the one below, but it is not working as I want.
Select
*,
(select Value where Period = 4) as MainValue
from myTable;
Any help would be appreciated.
Try this:
SELECT Period, Name, Value,
MAX(CASE WHEN Period=4 THEN Value END) OVER (PARTITION BY Name) AS MainValue
FROM mytable
The query uses a window function with a condition applied over Name partitions: the function returns the Value corresponding to Period=4 inside each partition.
You can do this a number of ways. A correlated sub-query as the column, a cross apply to a correlated query, or a cte. I personally like the cte approach. It would look something like this.
with MainValues as
(
select Name
, Value
from SomeTable
where Period = 4
)
select st.*
, mv.Value as MainValue
from SomeTable st
join MainValues mv on st.Name = mv.Name

complex paratition sum in postgresql

I have tables as follow:
A deliveries
delveryid clientid deliverydate
1 10 2015-01-01
2 10 2015-02-02
3 11 2015-04-08
B items in deliveris
itemid deliveryid qty status
70 1 5 1
70 1 8 2
70 2 10 1
72 1 12 1
70 3 100 1
I need to add a column to my query that gives me the qty of each part in other deliveris of the same client.
meaning that for given data of client 10 and delivery id 1 I need to show:
itemid qty status qtyOther
70 5 1 10 //itemid 70 exists in delivery 2
70 8 2 10 //itemid 70 exists in delivery 2
72 12 1 0 //itemid 72 doesn't exists in other delivery of client 11
Since I need to add qtyOther to my existing qry i'm trying to avoid using Group By as it's a huge query and if I use SUM in select I will have to group by all items in select.
This is what I have so far:
Select ....., coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid) ,0) AS qtyOther
FROM B b
LEFT JOIN A a USING
LEFT JOIN (other tables)
WHERE clientid=10 ....
This query gives me the total sum of qty per itemid for specific clientid, regardless of which delivery it is. How do I change it so it will consider the delivryid? I need something like:
coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid) FROM B where deliveryid<>b.deliveryid ,0) AS qtyOther
Any suggestions how to do that?
Note: I can NOT change the condition in WHERE.
I think you just want to subtract out the total for the current delivery:
Select .....,
(coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid), 0) -
coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid, a.deliveryid), 0)
) as qtyOther