Help I want to rename a column before using the unpivot method
My table is like this:
List item
id| value| ENE| FEB| MAR| ABR| MAY
1 | dsads|2000|2334|2344|2344|2344
after unpivot I get something like this
id| value| month| amount
1 | dads| ENE | 2000
2 | sadf| FEB | 2334
but I want something like this
id| value| month| amount
1 | dads| 01 | 2000
2 | sadf| 02 | 2334
This is my query
select
[año], [Empresa], [Region], [Suc], [CC], [Cuenta],
[Subcuenta], [Descripcion], Periodo, Importe
from
(select * from [dbo].['P Cargado$']) S
unpivot
(Importe for Periodo in
([ENE], [FEB], [MAR], [ABR], [MAY], [JUN], [JUL], [AGO], [SEP],[OCT], [NOV], [DIC])
) AS unpvt;
If you use cross apply(values ..) to unpivot, you could do so like this:
select t.id, t.value, x.*
from t
cross apply (values (1,ene),(2,feb),(3,mar),(4,abr),(5,may)) x (Mnth,Amount)
rextester demo: http://rextester.com/SZDP50356
returns:
+----+-------+------+--------+
| id | value | Mnth | Amount |
+----+-------+------+--------+
| 1 | dsads | 1 | 2000 |
| 1 | dsads | 2 | 2334 |
| 1 | dsads | 3 | 2344 |
| 1 | dsads | 4 | 2344 |
| 1 | dsads | 5 | 2344 |
+----+-------+------+--------+
Related
I am having trouble narrowing down sales in top regions that occurred in consecutive months. I know I need to use some form of window function with Row_Number or Dense_Rank, but I am having trouble getting the final output
Here is my source data:
+--------+-----------+------------+
| Fruit | SaleDate | Top_Region |
+--------+-----------+------------+
| Apple | 1/1/2017 | 1 |
| Apple | 2/1/2017 | 1 |
| Apple | 3/1/2017 | 1 |
| Apple | 4/1/2017 | 0 |
| Apple | 5/1/2017 | 0 |
| Apple | 6/1/2017 | 0 |
| Apple | 7/1/2017 | 1 |
| Apple | 8/1/2017 | 1 |
| Apple | 9/1/2017 | 1 |
| Apple | 10/1/2017 | 1 |
| Apple | 11/1/2017 | 0 |
| Apple | 12/1/2017 | 0 |
| Banana | 1/1/2017 | 0 |
| Banana | 2/1/2017 | 0 |
| Banana | 3/1/2017 | 1 |
| Banana | 4/1/2017 | 1 |
| Banana | 5/1/2017 | 1 |
| Banana | 6/1/2017 | 1 |
| Banana | 7/1/2017 | 1 |
| Banana | 8/1/2017 | 1 |
| Banana | 9/1/2017 | 0 |
| Banana | 10/1/2017 | 1 |
| Banana | 11/1/2017 | 1 |
| Banana | 12/1/2017 | 0 |
+--------+-----------+------------+
This is the expected output:
+--------+-----------+-----------+-------+
| Fruit | Start | End | Total |
+--------+-----------+-----------+-------+
| Apple | 1/1/2017 | 3/1/2017 | 3 |
| Apple | 7/1/2017 | 10/1/2017 | 4 |
| Banana | 3/1/2017 | 8/1/2017 | 6 |
| Banana | 10/1/2017 | 11/1/2017 | 2 |
+--------+-----------+-----------+-------+
The goal is to have instances of top region sales in succession with missing in one month.
So far I have tried a few different combinations, with this being the closest.
SELECT fruit,
MIN(saledate) AS spanStart ,
MAX(saledate) AS spanEnd,
COUNT(*) AS spanLength
FROM ( SELECT s.* ,
( ROW_NUMBER() OVER ( ORDER BY month )
- ROW_NUMBER() OVER ( PARTITION BY fruit, topregion ORDER BY month ) ) AS fruits
FROM #salesdata s
) s
GROUP BY fruit,fruits ,
topregion
HAVING topregion = 1
ORDER BY COUNT(*) DESC;
Any help would be greatly appreciated
This is a typical gaps-and-island problem. One strategy is to identify the groups of adjacent rows groups by computing the difference between two row_number()s. We can then filter on groups having top_region = 1 and use aggregation to get the start date, end date and number of records per group.
Your query is really close, but the first row_number() is missing a partition by fruit in its over() clause. And I find that aliasing that column fruits where another column is called fruit is error prone.
select
fruit,
min(sale_date) start_date,
max(sale_date) end_date,
count(*) total
from (
select
t.*,
row_number() over(partition by fruit order by sale_date) rn1,
row_number() over(partition by fruit, top_region order by sale_date) rn2
from mytable t
) t
where top_region = 1
group by fruit, rn1 - rn2
order by fruit, start_date
You can run the inner query separately to see the result it produces.
Demo on DB Fiddle:
fruit | start_date | end_date | total
:----- | :--------- | :--------- | ----:
Apple | 2017-01-01 | 2017-01-03 | 3
Apple | 2017-01-07 | 2017-01-10 | 4
Banana | 2017-01-03 | 2017-01-08 | 6
Banana | 2017-01-10 | 2017-01-11 | 2
I've been working on this issue for the last day and a half and just can't seem to find another question on here that works for my code.
I have a table here:
Table_D
Policynumber| EntryDate | BI_Limit | P remium
------------------------------------------------------
ABCD100001 | 5/1/16 | 15/30 | 919
ABCD100001 | 5/13/16 | 15/30 | 1008
ABCD100002 | 5/24/16 | 100/300 | 1380
ABCD100003 | 5/30/16 | 25/50 | 1452
ABCD100003 | 6/2/16 | 25/50 | 1372
ABCD100003 | 6/4/16 | 30/60 | 951
ABCD100004 | 6/11/16 | 100/300 | 1038
ABCD100005 | 6/22/16 | 100/300 | 1333
ABCD100005 | 7/2/16 | 50/100 | 1208
ABCD100006 | 7/10/16 | 250/500 | 1345
ABCD100007 | 7/18/16 | 15/30 | 996
in which I'm trying to extract rows in which a policynumber has multiple listings and a different BI_Limit. So the output should be:
Output
Policynumber | EntryDate | BI_Limit | Premium
---------------------------------------------------
ABCD100003 | 5/30/16 | 25/50 | 1452
ABCD100003 | 6/2/16 | 25/50 | 1372
ABCD100003 | 6/4/16 | 30/60 | 951
ABCD100005 | 6/22/16 | 100/300 | 1333
ABCD100005 | 7/2/16 | 50/100 | 1208
I'm storing Policynumber as VARCHAR(Max), EntryDate as DATE, BI_Limit as VARCHAR(Max), and Premium as INTEGER.
The code I've want to say should work would be something along the lines of:
SELECT * FROM Table_D
WHERE BI_Limit IN (
SELECT BI_Limit
FROM Table_D
GROUP BY BI_Limit
HAVING COUNT(DISTINCT BI_Limit)>1);
But this returns nothing for me. Can anyone help to show me what I'm doing wrong? Thank you.
You could also try exists
select a.*
from Table_D a
where
exists (
select 1
from Table_D b
where a.Policynumber = b.Policynumber
and a.BI_Limit <> b.BI_Limit
)
SELECT d.*
FROM ( -- find the policy number with multiple listing and diff BI_Limit
SELECT PolicyNumber
FROM TableD
GROUP BY PolicyNumber
HAVING count(*) > 1
AND MIN (BI_Limit) <> MAX (BI_Limit)
) m -- join back the Table_D to for other information
INNER JOIN Table_D d
ON m.PolicyNumber = d.PolicyNumber
My data looks like this:
| ACCNT | AMOUNT | TYPE | YEAR |
|-------|--------|------|------|
| 458 | 168.80 | A | 2014 |
| 458 | 282.77 | A | 2015 |
| 458 | 64.70 | B | 2015 |
| 458 | 91.25 | A | 2016 |
| 458 | 398.00 | B | 2016 |
| 458 | 104.45 | C | 2016 |
| 927 | 445.00 | B | 2014 |
| 927 | 25.00 | A | 2015 |
| 927 | 10.00 | NULL | 2015 |
| 927 | 132.00 | A | 2016 |
| 927 | 381.40 | B | 2016 |
| 927 | 210.00 | C | 2016 |
...
An Accnt might not have a value for each Year, and the Type will occasionally be NULL.
I want to have just one row per Accnt, and combine the Amount & Type columns under a Year heading, i.e. to get it looking like this:
| ACCNT | 2014 | 2015 | 2016 |
|-------|-----------|--------------------|----------------------------|
| 458 | 168.80,A | 282.77,A;64.70,B | 91.25,A;398.00,B;104.45,C |
| 927 | 445.00,B | 25.00,A;10.00,NULL | 132.00,A;381.40,B;210.00,C |
...
I can pivot on the [Year]...
SELECT * FROM
(SELECT [Accnt], [Amount], [Type], [Year] FROM data_table)
AS Source
PIVOT
(
MAX([Amount]) FOR [Year] IN ([2014],[2015],[2016])
) AS PVT
...but still end up with multiple rows per Accnt.
The following gets closer to the format I'm looking for...
SELECT Accnt, [1] AS '2014', [2] AS '2015', [3] AS '2016'
FROM (SELECT ROW_NUMBER() OVER (PARTITION BY Accnt ORDER BY [Year] Asc) AS AccountID,
Accnt, CONVERT(nvarchar,Amount) + ',' + [Type] AS Amount_And_Type
FROM data_table) PIVOT (MAX(Amount_And_Type)
FOR AccountID IN ([1], [2], [3])) AS data_pvt
...but it's just giving me the first three rows for each Accnt:
| ACCNT | 2014 | 2015 | 2016 |
|-------|-----------|----------|---------|
| 458 | 168.80,A | 282.77,A | 67.40,B |
| 927 | 445.00,B | 25.00,A | NULL |
Is what I'm trying to do even possible with a Pivot?
You can query as below:
;with cte as (
select Accnt, iif([2014] is null,null, concat([2014],',',[Type])) as [2014a]
,iif([2015] is null,null, concat([2015],',',[Type])) as [2015a]
,iif([2016] is null,null, concat([2016],',',[Type])) as [2016a]
from youracct
pivot(max(amount) for [year] in ([2014],[2015],[2016])) p
)
select c.Accnt, [2014]= stuff(( Select ';'+[2014a] from cte where Accnt = c.Accnt for xml path('')),1,1,'')
,[2015]=stuff(( Select ';'+[2015a] from cte where Accnt = c.Accnt for xml path('')),1,1,'')
,[2016]=stuff(( Select ';'+[2016a] from cte where Accnt = c.Accnt for xml path('')),1,1,'')
from cte c
group by c.Accnt
But dynamic sql for this approach is bit complex but we can do..
Output as below:
+-------+---------+-----------------+------------------------+
| Accnt | 2014 | 2015 | 2016 |
+-------+---------+-----------------+------------------------+
| 458 | 168.8,A | 282.77,A;64.7,B | 91.25,A;398,B;104.45,C |
| 927 | 445,B | 10,;25,A | 132,A;381.4,B;210,C |
+-------+---------+-----------------+------------------------+
I have a table with a data as bellow :
+--------+----------+-------+------------+--------------+
| month | code | type | date | PersonID |
+--------+----------+-------+------------+--------------+
| 201501 | 178954 | 3 | 2014-12-3 | 10 |
| 201501 | 178954 | 3 | 2014-12-3 | 10 |
| 201501 | 178955 | 2 | 2014-12-13 | 10 |
| 201501 | 178955 | 2 | 2014-12-13 | 10 |
| 201501 | 178956 | 2 | 2014-12-11 | 10 |
| 201501 | 178958 | 1 | 2014-12-10 | 10 |
| 201501 | 178959 | 2 | 2014-12-12 | 15 |
| 201501 | 178959 | 2 | 2014-12-12 | 15 |
| 201501 | 178954 | 1 | 2014-12-11 | 13 |
| 201501 | 178954 | 1 | 2014-12-11 | 13 |
+--------+----------+-------+------------+--------------+
In my first 6 lines i have the same PersonID in the same Month What i want if i have the same personID in the same Month i want to select the person who have the type is 2 with the recent date in my case the output will be like as bellow:
+--------+--------+------+------------+----------+
| month | code | type| date | PersonID |
+--------+--------+------+------------+----------+
| 201501 | 178955 | 2 | 2014-12-13 | 10 |
| 201501 | 178959 | 2 | 2014-12-12 | 15 |
| 201501 | 178954 | 2 | 2014-12-11 | 13 |
+--------+--------+------+------------+----------+
Also if they are some duplicate rows i don't want to display it
They are any solution to that ?
Simply use GROUP BY:
https://msdn.microsoft.com/de-de/library/ms177673(v=sql.120).aspx
SELECT mont, code, ... FROM tabelname GROUP BY PersonID, date, ...
Note that you have to specifiy all columns in the group by.
SELECT DISTINCT A.month, A.code, A.type, B.date, B.PersonID FROM YourTable A
INNER JOIN (SELECT PersonID, MAX(date) as date FROM YourTable
GROUP BY PersonID) B
ON (A.PersonID = B.PersonID
AND A.date = B.date)
WHERE A.type = 2 ORDER BY B.date DESC, A.PersonID
Just in case you/others are still wondering.
I have this simple query that brings the siblings of a given item.
select
PC.SKU
from
ProdC PC
where
Parent_ID in (select Parent_ID
from ProdC
where SKU = 4536)
and ParentFlag <> 'P'
and SKU <> 4536
I'd like to display up to 6 siblings horizontally. So it would look something like this:
Sib1 Sib2 Sib3 Sib4 Sib5 Sib6
=============================================
4532 4539 4548 4552 4561 4562
3512 3536
5632 5636 5640
Now each of these row are for a different item. some parent have 2 child, some have up to 8 but I only want to show 6 max. There's a priority column for the children. I can sort it by that column desc to get the 6 newest child.
Any help appreciated.
I have a table in my test database with records with multiple child records for each parent record, created the following query to only get the top 6 child records, but it only picks the immediate child records, if you have another level of children records then you probably need to look into recursive CTE etc.
;WITH X AS
(
Select *
,ROW_NUMBER() OVER (PARTITION BY Parent_ID ORDER BY ID) rn
from TableName
),
Y AS (
Select * , 'Sib' + Cast(rn AS Varchar(10)) Sibs
FROM X
Where rn < 7
)
Select *
from
(
Select Parent_ID , Sibs , ID
FROM Y
) a
PIVOT (MAX(ID)
FOR Sibs
IN (Sib1,Sib2,Sib3,Sib4,Sib5,Sib6))p
Result Set
+----------+------+------+------+------+-------+------+
| ParentID | Sib1 | Sib2 | Sib3 | Sib4 | Sib5 | Sib6 |
+----------+------+------+------+------+-------+------+
| 0 | 0 | 139 | 258 | 266 | 285 | 500 |
| 139 | 140 | 141 | 142 | 143 | 144 | 162 |
| 142 | 5062 | 5063 | NULL | NULL | NULL | NULL |
| 143 | 5041 | 5042 | 5043 | 5044 | 5045 | 5046 |
| 144 | 5050 | 5051 | 5052 | 5053 | 5054 | 5055 |
| 258 | 5823 | 5824 | 5825 | 5826 | 11269 | NULL |
| 266 | 5822 | 5912 | 5913 | 5914 | 5915 | 5916 |
| 285 | 2139 | 3855 | 4172 | 4173 | NULL | NULL |
+----------+------+------+------+------+-------+------+
EDIT
After you have provided some sample data your query should look something like..
;WITH X AS
(
Select *
,ROW_NUMBER() OVER (PARTITION BY Parent_Sku ORDER BY sku) rn
from #ProdC
),
Y AS (
Select * , 'Sib' + ISNULL(NULLIF(Cast(rn -1 AS Varchar(10)), '0'),'') Sibs
FROM X
Where rn < 8
)
Select Sib1,Sib2,Sib3,Sib4,Sib5,Sib6
from
(
Select Parent_Sku , Sibs , sku
FROM Y
) a
PIVOT (MAX(sku)
FOR Sibs
IN (Sib,Sib1,Sib2,Sib3,Sib4,Sib5,Sib6,Sib7))p
Result set
| Sib1 | Sib2 | Sib3 | Sib4 | Sib5 | Sib6 |
|------|------|------|--------|--------|--------|
| 4532 | 4536 | 4539 | 4548 | 4552 | (null) |
| 3512 | 3536 | 4561 | 4562 | (null) | (null) |
| 5632 | 5636 | 5640 | (null) | (null) | (null) |