I have a table such as http://sqlfiddle.com/#!6/e4f6f which contains records that need to be reported on an Excel using SSIS.
However, the ordering of records needs to be custom.
Such as below
AID BID CID CurrencyID ClassID Year MetricID Value ReferenceID
220 1 3 6 1147 2012 C1 653465.751842658967 V001
220 1 3 6 1147 2012 C2 0.000000000000 V001
220 1 3 6 1156 2012 C1 1151019.50078003120 V001
220 1 3 6 1156 2012 C2 0.000000000000 V001
As you can see the records are grouped such that they are ordered on ReferenceID first and then all the other dimension keys except the MetricID. Any help is much appreciated
Put MetricID as the last column in your ORDER BY:
SELECT *
FROM [FactValidationResult]
ORDER BY
ReferenceID,
AID,
BID,
CID,
CurrencyID,
Year,
ClassID,
MetricID
Related
I have 2 tables and am joining them on tinnumber, but we group the records based on PSKUCD so that we have a family of tinumbers under each pskucd. We are joining with MDM table because it has updated brandname. And MDM will have only parent tinumbers. I want to use the mdm brandname from table 2 to update for parent and child tinumber's brandname in snapshot table.
Table 1 (snapshot)
Pskucd tinnum brandname
234 9999 AMZ
234 10001 AMZt
Table 2 (MDM)
tinnum bdname
9999 RMZ
Desired Output
Pskucd tinnum brandname bdname
234 9999 AMZ RMZ
234 10001 AMZt RMZ
One option might be to use outer join with first_value analytic function (sample data from line #1 - 7; query that does the job begins at line #9).
SQL> with
2 snapshot (pskucd, tinnum, brandname) as
3 (select 234, 9999 , 'AMZ' from dual union all
4 select 234, 10001, 'AMZt' from dual
5 ),
6 mdm (tinnum, bdname) as
7 (select 9999, 'RMZ' from dual)
8 --
9 select s.pskucd,
10 s.tinnum,
11 s.brandname,
12 first_value(m.bdname) over (order by null) bdname
13 from snapshot s left join mdm m on m.tinnum = s.tinnum;
PSKUCD TINNUM BRANDNAME BDNAME
---------- ---------- ---------- ----------
234 9999 AMZ RMZ
234 10001 AMZt RMZ
SQL>
So I have this one giant table e.g.
PROD_IDGEOG_IDTIME_IDVALUE1
1 MT JAN 100
1 MT FEB 100
2 MT JAN 100
2 MT FEB 100
3 TT MARCH 100
And I want to receive Jan and Feb data only in the geography MT. Then sum the Value1's together where PROD_ID matches.
So the end result is:
PROD_IDGEOG_IDVALUE1
1 MT 200
2 MT 200
I have managed to get the data down to TIME_ID only using:
SELECT PROD_ID, GEOG_ID, TIME_ID, VALUE1 FROM database WHERE GEOG_ID = 'MT' AND TIME_ID IN ('JAN', 'FEB')
so I have :
PROD_IDGEOG_IDTIME_IDVALUE1
1 MT JAN 100
1 MT FEB 100
2 MT JAN 100
2 MT FEB 100
but now I am unsure how to use the group by function on PROD_ID since TIME_ID is unique.
Any thoughts?
Many thanks!
You can use the TIME_ID in the where clause without selecting it, meaning it doesn't have to go in the group by statement.
SELECT PROD_ID, GEOG_ID, SUM(VALUE1) AS TOTAL
FROM database
WHERE GEOG_ID = 'MT'
AND TIME_ID IN ('JAN', 'FEB')
GROUP BY PROD_ID, GEOG_ID
I have the below data, and I performed a ROW_NUMBER(partition by ID order by YEAR) function based on year which's ranking my data as below.
I want to bring in name for every id based on their latest year. I want to bring in NULL data if that's the only data available and bring in latest NON NULL data for every other record. But rownumber only lets me bring in recent name which could be NULL. How do I query below data to bring in most recent NON NULL name?
ID year name rownum
10 2011 abc 1
10 2010 abc 2
11 2011 ghi 1
11 2010 ghi 1
13 2010 NULL 1
13 2009 jkl 2
14 2014 NULL 1
14 2014 mno 2
15 2015 NULL 1
I want to bring in names jkl, mno for ID's 13 and 14 and not NULLS in my final result. Any suggestion on how to achieve that?
The output I desire is below - I want to display data for ROW NUM=1
10 2011 abc
11 2011 ghi
13 2009 jkl
14 2014 mno
15 2015 NULL
Sort non-null rows ahead of null rows:
select ID, year, name
from (select *,
row_number() over (partition by ID
order by case when name is null then 1 else 0 end, year desc) as RN
from #t) _
where rn = 1
See also SQL Server equivalent to Oracle's NULLS FIRST?, SQL Server ORDER BY date and nulls last &
for SQL Server 2008 R2
I have a resultset that looks like this (note [price] is numeric, NULL below represents a
NULL value, the result set is ordered by product_id and timestamp)
product timestamp price
------- ---------------- -----
5678 2008-01-01 12:00 12.34
5678 2008-01-01 12:01 NULL
5678 2008-01-01 12:02 NULL
5678 2008-01-01 12:03 23.45
5678 2008-01-01 12:04 NULL
I want to transform that to a result set that (essentially) copies a non-null value from the latest preceding row, to produce a resultset that looks like this:
product timestamp price
------- ---------------- -----
5678 2008-01-01 12:00 12.34
5678 2008-01-01 12:01 12.34
5678 2008-01-01 12:02 12.34
5678 2008-01-01 12:03 23.45
5678 2008-01-01 12:04 23.45
I don't find any aggregate/windowing function that will allow me to do this (again this ONLY needed for SQL Server 2008 R2.)
I was hoping to find an analytic aggregate function that do this for me, something like...
LAST_VALUE(price) OVER (PARTITION BY product_id ORDER BY timestamp)
But I don't seem to find any way to do a "cumulative latest non-null value" in the window (to bound the window to the preceding rows, rather than the entire partition)
Aside from creating a table-valued user defined function, is there any builtin that would accomplish this?
UPDATE:
Apparently, this functionality is available in the 'Denali' CTP, but not in SQL Server 2008 R2.
LAST_VALUE http://msdn.microsoft.com/en-us/library/hh231517%28v=SQL.110%29.aspx
I just expected it to be available in SQL Server 2008. It's available in Oracle (since 10gR2 at least), and I can do something similar in MySQL 5.1, using a local variable.
http://download.oracle.com/docs/cd/E14072_01/server.112/e10592/functions083.htm
You can try the following:
* Updated **
-- Test Data
DECLARE #YourTable TABLE(Product INT, Timestamp DATETIME, Price NUMERIC(16,4))
INSERT INTO #YourTable
SELECT 5678, '20080101 12:00:00', 12.34
UNION ALL
SELECT 5678, '20080101 12:01:00', NULL
UNION ALL
SELECT 5678, '20080101 12:02:00', NULL
UNION ALL
SELECT 5678, '20080101 12:03:00', 23.45
UNION ALL
SELECT 5678, '20080101 12:04:00', NULL
;WITH CTE AS
(
SELECT *
FROM #YourTable
)
-- Query
SELECT A.Product, A.Timestamp, ISNULL(A.Price,B.Price) Price
FROM CTE A
OUTER APPLY ( SELECT TOP 1 *
FROM CTE
WHERE Product = A.Product AND Timestamp < A.Timestamp
AND Price IS NOT NULL
ORDER BY Product, Timestamp DESC) B
--Results
Product Timestamp Price
5678 2008-01-01 12:00:00.000 12.3400
5678 2008-01-01 12:01:00.000 12.3400
5678 2008-01-01 12:02:00.000 12.3400
5678 2008-01-01 12:03:00.000 23.4500
5678 2008-01-01 12:04:00.000 23.4500
I have a table containing the following data. I want to update all nulls in salary columns with previous value without taking null value.
Table:
id name salary
1 A 4000
2 B
3 C
4 C
5 D 2000
6 E
7 E
8 F 1000
9 G 2000
10 G 3000
11 G 5000
12 G
here is the query that works for me.
select a.*,first_value(a.salary)over(partition by a.value order by a.id) as abc from
(
select *,sum(case when salary is null then 0 else 1 end)over(order by id) as value from test)a
output:
id name salary Value abc
1 A 4000 1 4000
2 B 1 4000
3 C 1 4000
4 C 1 4000
5 D 2000 2 2000
6 E 2 2000
7 E 2 2000
8 F 1000 3 1000
9 G 2000 4 2000
10 G 3000 5 3000
11 G 5000 6 5000
12 G 6 5000
Try this:
;WITH SortedData AS
(
SELECT
ProductID, TimeStamp, Price,
ROW_NUMBER() OVER(PARTITION BY ProductID ORDER BY TimeStamp DESC) AS 'RowNum'
FROM dbo.YourTable
)
UPDATE SortedData
SET Price = (SELECT TOP 1 Price
FROM SortedData sd2
WHERE sd2.RowNum > SortedData.RowNum
AND sd2.Price IS NOT NULL)
WHERE
SortedData.Price IS NULL
Basically, the CTE creates a list sorted by timestamp (descending) - the newest first. Whenever a NULL is found, the next row that contains a NOT NULL price will be found and that value is used to update the row with the NULL price.
I am struggling to write a query to result in the following records.
I have a table with records as
c1 c2 c3 c4 c5 c6
1 John 2.3.2010 12:09:54 4 7 99
2 mike 2.3.2010 13:09:59 8 6 88
3 ahmad 2.3.2010 14:09:59 1 9 19
4 Jim 23.3.2010 16:35:14 4 5 99
5 run 23.3.2010 12:09:54 3 8 12
I want to fetch only the records :-
3 ahmad 2.3.2010 14:09:59 1 9 19
4 Jim 23.3.2010 16:35:14 4 5 99
I mean the records that are sort by column c3 and the one which is latest for that day. here i have 1, 2, 3 records that are at different times of the day. there i need the records that are sort by date desc and then only top 1 record. similarly for 4 and 5. can you please help me in writing a query.
If you're on SQL Server 2008 or 2008 R2, you can try this:
WITH TopPerDay AS
(
SELECT
c1, c2, c3, c4, c5, C6,
ROW_NUMBER() OVER
(PARTITION BY CAST(c3 AS DATE) ORDER BY c3 DESC) 'RowNum'
FROM dbo.YourTable
)
SELECT *
FROM TopPerday
WHERE RowNum = 1
I basically partition the data by day (using the DATE type in SQL Server 2008 and up), and order by the c3 column in a descending order. This means, for every day, the oldest row will have RowNum = 1 - so I just select those rows from the Common Table Expression and I'm done.
Tried this on a SQL Server 2005 database.
SELECT *
FROM dbo.YourTable t1
WHERE (t1.c3) =
(
SELECT MAX(t2.c3)
FROM dbo.YourTable t2
WHERE DATEDIFF(dd,t2.c3, t1.c3) = 0
)
ORDER BY t1.c3 ASC
Thanks for the responses!
I have found the solution too.
select * from
(select convert(varchar(10),c3,104) as date, max(c3) as date1 from MYTABLE
group by convert(varchar(10),c3,104)) as T1 innerjoin MYTABLE as T2 on
convert(varchar(10),T2.c3,104) = T1.date and t2.c3 = T2.date1