Building SQL Query - asp.net

I need some help to build SQL Query. I have table having data like:
ID Date Value1 Value2 Code
1 12/01/2009 4 3.5 abc
2 12/02/2009 3 4.0 abc
3 11/03/2009 6 8.5 xyz
4 11/01/2009 2 5.5 abc
5 11/02/2009 4 6.0 xyz
6 12/03/2009 5 7.0 xyz
I need to show result something like...
---------
Code | Data | November(Sum of Values in month) December Jan Feb
abc | Value1 | 2 7 0 0
| Value2 | 5 7 0 0
xyz | Value1 | 10 5 0 0
| Value2 | 14 7 0 0
----------
I need sum of value in each month as in above data in columns group by code.

Have a look at this solution, and let me know what you think.
You have to use both PIVOT and UNPIVOT in this instance to get the result you are looking for. Hope this helps.
DECLARE #Table TABLE(
ID INT,
Date DATETIME,
Value1 INT,
Value2 FLOAT,
Code VARCHAR(10)
)
INSERT INTO #Table (ID,Date,Value1,Value2,Code) SELECT 1,'12/01/2009',4,3,'abc'
INSERT INTO #Table (ID,Date,Value1,Value2,Code) SELECT 2,'12/02/2009',3,4,'abc'
INSERT INTO #Table (ID,Date,Value1,Value2,Code) SELECT 3,'11/03/2009',6,8,'xyz'
INSERT INTO #Table (ID,Date,Value1,Value2,Code) SELECT 4,'11/01/2009',2,5,'abc'
INSERT INTO #Table (ID,Date,Value1,Value2,Code) SELECT 5,'11/02/2009',4,6,'xyz'
INSERT INTO #Table (ID,Date,Value1,Value2,Code) SELECT 6,'12/03/2009',5,7,'xyz'
;WITH UnPvt AS (
SELECT *
FROM (
SELECT Code,
DATENAME(MM, Date) MonthNameVal,
SUM(Value1) Value1,
SUM(Value2) Value2
FROM (
SELECT Code,
Date,
CAST(Value1 AS FLOAT) Value1,
Value2
FROM #Table
) v
GROUP BY Code,
DATENAME(MM, Date)
) Sub
UNPIVOT
(
Vals FOR RowValues IN (Value1, Value2)
) AS UnPvt
)
SELECT *
FROM UnPvt
PIVOT (
SUM(Vals)
FOR MonthNameVal IN ([January],[February],[March],[April],[May],[June],[July],[August],[September],[October],[November], [December])
) AS pvt
ORDER BY Code, RowValues
Have a look at
SQL SERVER – PIVOT and UNPIVOT Table
Examples
Give the New PIVOT and UNPIVOT
Commands in SQL Server 2005 a
Whirl
Using PIVOT and UNPIVOT

This isn't quite what you asked for because the number of columns is fixed, but I think it's a better way to what you want in SQL:
SELECT Code, 'Value1' As Data, MONTH(Date) AS Month, YEAR(Date) AS Year, SUM(Value1) AS Sum
FROM Table1
GROUP BY Code, MONTH(Date), YEAR(Date)
UNION ALL
SELECT Code, 'Value2' As Data, MONTH(Date) AS Month, YEAR(Date) AS Year, SUM(Value2) AS Sum
FROM Table1
GROUP BY Code, MONTH(Date), YEAR(Date)
ORDER BY Code, Data, Month, Year
Example output:
Code Data Month Year Sum
abc Value1 11 2009 2
abc Value1 12 2009 7
abc Value2 11 2009 5
abc Value2 12 2009 7
xyz Value1 11 2009 10
xyz Value1 12 2009 5
xyz Value2 11 2009 14
xyz Value2 12 2009 7
I'd recommend that you use a bit of non-SQL code to reformat the result into exactly what you asked for before displaying it to the user rather than trying to return a variable number of columns in SQL.

Related

Data Wrangling for Analysis Services Cube

I have a data set that is as follows (simplified):
Fund Field1-2012 Field1-2013 Field2-2012 Field2-2013
FD1 x x x x
FD2 x x x x
As you can see, dates exist with the fields making this very unfriendly for most analysis. What want is the following
Fund Year Field1 Field2
FD1 2012 x x
FD1 2013 x x
FD2 2012 x x
FD2 2013 x x
I have been using SQL server integration tools to accomplish this but to no avail. Is there a tool I should be using or is there something in excel that can help me out? Not possible to brute force as the dataset is quite large
Best
You have an R tag, so here's an R solution:
df = read.table(text = "
Fund Field1-2012 Field1-2013 Field2-2012 Field2-2013
FD1 5 7 9 10
FD2 6 8 9 10
", header=T)
library(tidyverse)
df %>%
gather(key, value, -Fund) %>%
separate(key, c("type","year"), convert = T) %>%
spread(type, value)
# Fund year Field1 Field2
# 1 FD1 2012 5 9
# 2 FD1 2013 7 10
# 3 FD2 2012 6 9
# 4 FD2 2013 8 10
You can use apply to unpivot the data :
select t.Fund, tt.year, tt.Field1, tt.Field2
from table t cross apply
( values (2012, [Field1-2012], [Field2-2012]),
(2013, [Field1-2013], [Field2-2013])
) tt (year, Field1, Field2);
One option would be to use union all:
select fund, 2012 as year, Field1-2012 as field1, Field2-2012 as field2
from yourtable
union all
select fund, 2013 as year, Field1-2013 as field1, Field2-2013 as field2
from yourtable

PLSQL Dynamic Row Count in results

In PL SQL is there a way to produce the Order Count per customer as follows... Thanks for your help.
Cust Order# Order Count
ABC1 011 1
ABC1 052 2
ABC1 199 3
BBA1 150 1
BBA1 158 2
Thanks
Gavin
If I understood you correctly, a little bit of analytics might do the job. Here's an example:
SQL> with test (cust, order#) as
2 (select 'ABC1', '011' from dual union all
3 select 'ABC1', '052' from dual union all
4 select 'ABC1', '199' from dual union all
5 select 'BBA1', '150' from dual union all
6 select 'BBA1', '158' from dual
7 )
8 select cust, order#,
9 row_number() over (partition by cust order by order#) order_count
10 from test;
CUST ORD ORDER_COUNT
---- --- -----------
ABC1 011 1
ABC1 052 2
ABC1 199 3
BBA1 150 1
BBA1 158 2
SQL>
sounds like you want a GROUP BY such as
select cust, SUM(order_count)
from MyTable
group by cust;
which should yield
cust SUM
ABC1 6
BBA1 3

PL/SQL, CASE statement or if statement

I am new to PL/SQL
I have a code like this
SELECT f.code,f.date,f.amt, row_number() OVER (PARTITION BY f.code ORDER BY f.date DESC) ranki
FROM advance.alloc f
and shows
CODE DATE AMT ranki
122 12/31/2016 3 1
122 12/31/2015 7 2
122 12/31/2014 3 3
123 6/30/2015 3 1
125 6/30/2015 2 1
125 12/31/2014 8 2
Logic is this
if DATE = 12/__/__ AND ranki = 1 THEN ranki 1, so 122 picks 12/31/2016 3
if DATE = 6/30/__ AND ranki = 1 AND if ranki = 2 exists THEN then pick the second one,so 125 picks 12/31/2014 8
if 6/30__ and ranki is ONLY 1 shows Blank on date LIKE 123
so I would like to show
122 12/31/2016 3
123 __________ 3
125 12/31/2014 8
How can I code like this PL/SQL?
WHEN to_char(af.date,'MM') = 12 AND af.ranki = 1 THEN af.date END
I could code first logic, but I can not figure out how to code the rest of the logic
Thanks
Why in PL/SQL? Or do you mean "in Oracle SQL"? (The solution below uses standard analytic functions, so it is not specific to Oracle.)
Add more information through analytic functions, in addition to ranki. Extract the month from the row with ranki = 1, and also the total count for each code. Then the WHERE clause can follow your logic step by step.
with
f ( code, dt, amount ) as (
select 122, to_date('12/31/2016', 'mm/dd/yyyy'), 3 from dual union all
select 122, to_date('12/31/2015', 'mm/dd/yyyy'), 7 from dual union all
select 122, to_date('12/31/2014', 'mm/dd/yyyy'), 3 from dual union all
select 123, to_date( '6/30/2015', 'mm/dd/yyyy'), 3 from dual union all
select 125, to_date( '6/30/2015', 'mm/dd/yyyy'), 2 from dual union all
select 125, to_date('12/31/2014', 'mm/dd/yyyy'), 8 from dual
)
-- End of simulated data (for testing purposes only, not part of the solution).
-- SQL query begins BELOW THIS LINE.
select code, case when mth = 12 or ranki = 2 then dt end as dt, amount
from ( select code, dt, amount,
first_value(extract (month from dt))
over (partition by code order by dt desc) as mth,
row_number() over (partition by code order by dt desc) as ranki,
count(*) over (partition by code) as cnt
from f
)
where mth = 12 and ranki = 1
or cnt = 1
or mth = 6 and ranki = 2
;
CODE DT AMOUNT
---- ---------- ------
122 12/31/2016 3
123 3
125 12/31/2014 8

Lead function group by in oracle

I want to group by lead function by two column. Here is my table data.
Id Name_Id Name Item_Id Item_Name date
1 1 Car 1 SUV 1-Jan-2015
2 1 Car 1 SUV 12-March-2015
3 1 Car 1 SUV 20-April-2015
4 1 Car 2 Sport 23-April-2015
5 2 Bike 1 SUV 18-July-2015
6 2 Bike 1 SUV 20-Aug-2015
7 2 Bike 2 Sport 18-Sept-2015
8 2 Bike 3 Honda 20-OCT-2015
And I need result from above table like.
Id Name_Id Name Item_Id Item_Name start date end date
1 1 Car 1 SUV 1-Jan-2015 20-April-2015
2 1 Car 2 Sport 20-April-2015 23-April-2015
3 2 Bike 1 SUV 18-July-2015 20-Aug-2015
4 2 Bike 2 Sport 20-Aug-2015 18-Sept-2015
5 2 Bike 3 Honda 18-Sept-2015 20-OCT-2015
Any suggestion really appreciated.
I don't think you need to use LEAD here. The CTE below computes, for each Item_Id, the earliest and latest date. This is then joined to your original table to restrict to records corresponding to the earliest Item_Id. At the same time, the end date is also pulled in during the join.
WITH cte AS (
SELECT Name,
Item_Id,
MIN(date) AS start_date,
MAX(date) AS end_date
FROM yourTable
GROUP BY Name, Item_Id
)
SELECT t1.Id, t1.Name_Id, t1.Name, t1.Item_Id, t1.Item_Name,
t2.start_date,
t2.end_date
FROM yourTable t1
INNER JOIN cte t2
ON t1.Item_Id = t2.Item_Id AND
t1.Name = t2.Name AND
t1.date = t2.start_date

get entire row with MAX() on several columns

first off: thanks for looking; your time is appreciated!
to the point:
SCHEMA: for myTable
nonUniqueID YEAR MONTH DAY HOUR numericValue
1 2012 01 01 01 99.9
1 2012 01 01 02 65.2
1 2012 01 01 03 -88
7 2012 02 08 21 9.08
1 2012 01 01 09 99.913
1 2013 01 01 01 99.999999
Basically, it's two values nonUniqueID and numericValue with a granular date.
Now, i need to get the single greatest date in this entire database. With the data above, the expected result would be:
nonUniqueID YEAR MONTH DAY HOUR numericValue
1 2013 01 01 01 99.999999
Because this is SQLite, i know that i will end up having to use MAX() several times. The order will have to be MAX(YEAR) then MAX(MONTH) then MAX(DAY) then MAX(HOUR).
Basically, the query would work like this (i just don't know enough about SQL syntax to create the query):
Find all records with highest YEAR
From this set, find all records with highest MONTH
From this set, find all records with highest DAY
From this set, find all records with highest HOUR
return this record
Here is a SQL that i adapted from another StackExchange question that does not work
Select * From (
Select max(YEAR) as Y FROM myTable
union
Select max(MONTH) as M FROM myTable
union
Select max(DAY) as D FROM myTable
union
Select max(HOUR) as H FROM myTable
) myTable;
which returns
Y
-----
21
08
02
2013
Compare this to expected out:
nonUniqueID YEAR MONTH DAY HOUR numericValue
1 2013 01 01 01 99.999999
it returned 4 records instead of the one record with the 4 values.
Can somebody please help me with my query? THANK YOU!
Try this
SELECT nonUniqueID , YEAR , MONTH , DAY , HOUR , numericValue FROM myTable as a
INNER JOIN (Select max(MONTH) FROM myTable) as b
ON a.YEAR = B.YEAR
INNER JOIN (Select max(DAY) FROM myTable) as c
ON b.YEAR = c.YEAR
INNER JOIN (Select max(HOUR) FROM myTable) as d
ON c.YEAR = d.YEAR
WHERE a.YEAR = (Select max(YEAR) FROM myTable)
It returns 4 values because you use UNION
it means that the result are join in one column
EDIT
Ive just updated my answer see if that works Im not quite sure to the performance of this query

Resources