I have the following SQL code that uses the lag function.
SELECT SalesAmount
,lag(SalesAmount) OVER (
ORDER BY DATE
) AS PreviousDaylSales
,(
SalesAmount - (
lag(SalesAmount) OVER (
ORDER BY DATE
)
)
) AS Difference
,(
SalesAmount - (
lag(SalesAmount) OVER (
ORDER BY DATE
)
)
) / (
lag(SalesAmount) OVER (
ORDER BY DATE
)
) * 100 AS PercentChange
FROM Sheet1$
Can I format the alias column PercentChange values with a % char?
Yes, you can use square bracket []:
select . . . as [%Change]
from Sheet1$;
You can use sub-query to avoid repetition of same expression :
SELECT t.*, (SalesAmount - PreviousDaylSales) AS AS Difference,
CONCAT('%', SalesAmount - PreviousDaylSales / PreviousDaylSales * 100) AS [%Change]
FROM (SELECT SalesAmount, lag(SalesAmount) OVER (ORDER BY DATE) AS PreviousDaylSales
FROM Sheet1$
) t;
You can use CONCAT function.
select ...
CONCAT(...*100, '%') as PercentChange
from Sheet1$
Related
I have a select distinct query that can return 2 rows with the same code since not all columns have the same value. Now my boss wants to get the first one. So how to I do it. Below is the sample result. I want only to return the get the first two unique pro
Use row_number in your query. Please find this link for more info link
; with cte as (
select row_number() over (partition by pro order by actual_quantity) as Slno, * from yourtable
) select * from cte where slno = 1
Your chances to get the proper answer can be much higher if you spend some time to prepare the question properly. Provide the DDL and sample data, as well as add the desired result.
To solve your problem, you need to know the right uniqueness order to get 1 record per window group. Google for window functions. In my example the uniqueness is --> Single row for every pro with earliest proforma_invoice_received_date date and small amount per this date.
DROP TABLE IF EXISTS #tmp;
GO
CREATE TABLE #tmp
(
pro VARCHAR(20) ,
actual_quantity DECIMAL(12, 2) ,
proforma_invoice_received_date DATE ,
import_permit DATE
);
GO
INSERT INTO #tmp
( pro, actual_quantity, proforma_invoice_received_date, import_permit )
VALUES ( 'N19-00945', 50000, '20190516', '20190517' ),
( 'N19-00945', 50001, '20190516', '20190517' )
, ( 'N19-00946', 50002, '20190516', '20190517' )
, ( 'N19-00946', 50003, '20190516', '20190517' );
SELECT a.pro ,
a.actual_quantity ,
a.proforma_invoice_received_date ,
a.import_permit
FROM ( SELECT pro ,
actual_quantity ,
proforma_invoice_received_date ,
import_permit ,
ROW_NUMBER() OVER ( PARTITION BY pro ORDER BY proforma_invoice_received_date, actual_quantity ) AS rn
FROM #tmp
) a
WHERE rn = 1;
-- you can also use WITH TIES for that to save some lines of code
SELECT TOP ( 1 ) WITH TIES
pro ,
actual_quantity ,
proforma_invoice_received_date ,
import_permit
FROM #tmp
ORDER BY ROW_NUMBER() OVER ( PARTITION BY pro ORDER BY proforma_invoice_received_date, actual_quantity );
DROP TABLE #tmp;
Try this-
SELECT * FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY pro ORDER BY Pro) RN
-- You need to add other columns in the ORDER BY clause
-- with 'pro' to get your desired row. other case you
-- will get first row returned by the query with only
-- order by 'pro' and this can vary for different execution
FROM your_table
)A
WHERE RN = 1
CREATE TABLE T (
A [numeric](10, 2) NULL,
B [numeric](10, 2) NULL
)
INSERT INTO T VALUES (100,20)
INSERT INTO T VALUES (100,30)
INSERT INTO T VALUES (200,40)
INSERT INTO T VALUES (200,50)
select *
from T
/*
A B
100.00 20.00
100.00 30.00
200.00 40.00
200.00 50.00
*/
select U.A, U.B
from
(select row_number() over(Partition By A Order By B) as row_num, *
from T ) U
where row_num = 1
/*
A B
100.00 20.00
200.00 40.00
*/
Table:
How can I scan each individual SampleRef and flag the one that have any of the delivery dates more than 6 months apart. So from the sample above only SampleRef A has dates that are 6 months apart example 01/04/2013 and 16/02/2014 using T-SQL.
Result:
Thank you!
Couple other options for you:
MIN and MAX per SampleRef and difference of those greater than 6 months.
Or use LAG() and get the previous delivery date for each record and then see which one had a previous delivery greater than six months.
DECLARE #TestData TABLE
(
[SampleRef] CHAR(1)
, [DeliveryDate] DATE
);
INSERT INTO #TestData (
[SampleRef]
, [DeliveryDate]
)
VALUES ( 'A', '4/1/2013' )
, ( 'A', '2/3/2013' )
, ( 'A', '2/16/2014' )
, ( 'A', '6/12/2015' )
, ( 'A', '6/26/2015' )
, ( 'A', '6/26/2015' )
, ( 'A', '2/10/2015' )
, ( 'B', '6/26/2015' )
, ( 'B', '6/27/2015' )
, ( 'B', '6/28/2015' )
, ( 'B', '6/29/2015' )
, ( 'B', '6/30/2015' )
, ( 'B', '7/1/2015' );
--This looks at all dates per sampleref, min and max and filters those greater than 6 months
SELECT *
FROM (
SELECT [SampleRef]
, MIN([DeliveryDate]) AS [MinDeliveryDate]
, MAX([DeliveryDate]) AS [MaxDeliveryDate]
FROM #TestData
GROUP BY [SampleRef]
) AS [SampleRef]
WHERE DATEDIFF(
MONTH
, [SampleRef].[MinDeliveryDate]
, [SampleRef].[MaxDeliveryDate]
) > 6;
--This will get the prior delivery date for each record and then you can see all where there was a span greater than six months.
SELECT *
, DATEDIFF(
MONTH
, [SampleRef].[PreviousDelivery]
, [SampleRef].[DeliveryDate]
) AS [MonthSincePreviousDelivery]
FROM (
SELECT *
, LAG([DeliveryDate], 1, [DeliveryDate]) OVER ( PARTITION BY [SampleRef]
ORDER BY [DeliveryDate]
) AS [PreviousDelivery]
FROM #TestData
) AS [SampleRef]
WHERE DATEDIFF(
MONTH
, [SampleRef].[PreviousDelivery]
, [SampleRef].[DeliveryDate]
) > 6;
--Is there a record belonging to a SampleRef, where for any row, there is an absence of any
--delivery within six months prior, however there is some prior delivery
SELECT
DISTINCT T1.SampleRef FROM YourTable T1
WHERE EXISTS(
SELECT 0 FROM YourTable T2
WHERE
T1.SampleRef = T2.SampleRef And
Not EXISTS( -- was there no delivery in last 6 months
SELECT 0 FROM YourTable T3
WHERE T3.SampleRef = T2.SampleRef
AND
T3.DeliverYdate >= DATEADD(mm,-6,T2.DeliveryDate)
AND
T3.DeliveryDate < T2.DeliveryDate
)
And Exists --check that there was howevwer a prior delivery
(
SELECT 0 FROM YourTable T4
WHERE T4.SampleRef = T2.SampleRef
AND
T4.DeliverYdate < T2.DeliveryDate
)
)
You can use ROW_NUMBER() to order the samples within a SampleRef, then join that ordered set to itself and find any records where the next available sample is more than 6 months later. (Note that the example code below won't tell you if it's been more than 6 months since the final sample in the set - you could modify the query to do so if necessary)
You didn't specify a name for the table, so replace YourTableNameHere in the query below with the name of your table.
WITH SamplesNumberedByGroup AS (
SELECT
SampleRef,
DeliveryDate,
ROW_NUMBER() OVER (PARTITION BY SampleRef ORDER BY DeliveryDate) AS 'SampleNum'
FROM
YourTableNameHere
)
SELECT
DISTINCT
S.SampleRef
FROM
SamplesNumberedByGroup S
INNER JOIN SamplesNumberedByGroup S2 ON S.SampleRef = S2.SampleRef AND S2.SampleNum = S.SampleNum + 1
WHERE
S2.DeliveryDate > DATEADD(MONTH,6,S.DeliveryDate);
If you want to see each sample where the next available sample is more than 6 months away (instead of just seeing which sampleref has a gap of at least 6 months), use the code below instead.
WITH SamplesNumberedByGroup AS (
SELECT
SampleRef,
DeliveryDate,
ROW_NUMBER() OVER (PARTITION BY SampleRef ORDER BY DeliveryDate) AS 'SampleNum'
FROM
YourTableNameHere
)
SELECT
S.SampleRef
,S.Price
,S.DeliveryDate
FROM
SamplesNumberedByGroup S
INNER JOIN SamplesNumberedByGroup S2 ON S.SampleRef = S2.SampleRef AND S2.SampleNum = S.SampleNum + 1
WHERE
S2.DeliveryDate > DATEADD(MONTH,6,S.DeliveryDate);
If you need to include any entries that are more than 6 months old but do not have a "next" entry as well, then replace INNER JOIN with LEFT OUTER JOIN and add OR (S2.DeliveryDate IS NULL AND GETDATE() > DATEADD(MONTH,6,S.DeliveryDate) to the where statement.
Use EXISTS() to check if there is any row where the next higher row for the same SampleRef is more than 6 months DATEDIFF.
I Have this table :
create table #tmpState
( sheet_id int, -- person sheet id
qnumber int, -- Question number
lsn_id int, -- lesson Id
qstate nvarchar(1) -- 'T' , 'F' , 'W'
)
I want to calculate this formula :
(((res.T - (res.F*(#FactorA/#FactorB)))*100)/count(res.lsn_id)) as lsnpercent
-- count(res.lsn_id) : count number of Question per lesson
now i write this select query :
select * ,
(((res.T - (res.F*(#FactorA/#FactorB)))*100)/count(res.lsn_id)) as lsnpercent
from (select *
from
(select lsn_id , qstate from #tmpState ) as s
pivot
(
count(qstate)
for [qstate] in (T,F,W)
) as pvt
) as res
the #tmpState table fill :
when i run this Query :
select *
from
(select lsn_id , qstate from #tmpState ) as s
pivot
(
count(qstate)
for [qstate] in (T,F,W)
) as pvt
result is :
Problem :
I want to add Column to second table that calculate
this formula :
((res.T - (res.F*(#FactorA/#FactorB)))*100)/count(res.lsn_id))
like this:
when i run this query :
select * ,
(((res.T - (res.F*(#FactorA/#FactorB)))*100)/count(res.lsn_id)) as lsnpercent
from (select *
from
(select lsn_id , qstate from #tmpState ) as s
pivot
(
count(qstate)
for [qstate] in (T,F,W)
) as pvt
) as res
Message Error :
Msg 8120, Level 16, State 1, Line 122 Column 'res.lsn_id' is invalid
in the select list because it is not contained in either an aggregate
function or the GROUP BY clause.
For SQL Server 2008 R2 (SP3) you have to use
select pvt.[lsn_id], pvt.[T], pvt.[F], pvt.[W]
,[lsnpercent] = ((pvt.[T] - (pvt.[F] * (#FactorA/#FactorB))) * 100)/count(*) over()
from (select [lsn_id], [qstate] from #tmpState) as s
pivot (count(s.[qstate]) for s.[qstate] in ([T], [F], [W])) as pvt
You can change formula to this:
((res.T - (res.F*(#FactorA/#FactorB)))*100)/count(*) OVER (ORDER BY (SELECT 1)))
Every row has its own lsn_id so you can count all rows with OVER clause.
I have an example where we prepared query in sql for fetching appropriate results
SQL Query-
select partnerid,BrandDesc,ActualRetailValue
from
(
select DENSE_RANK() over (partition by partnerid order by sum(ActualRetailValue) desc) as rnk,
partnerid,BrandDesc,sum(ActualRetailValue) as ActualRetailValue
from JDASales
where partnerid in (693,77)
group by partnerid,BrandDesc
) as A
where rnk <=5
order by partnerid,rnk
Output -
I want this result with mdx query.Even tryout with this code
SELECT
NON EMPTY
{[Measures].[Actual Retail Value]} ON COLUMNS
,NON EMPTY
[DimBrands].[Brand].[Brand].ALLMEMBERS
*
TopCount
(
[DimPartners].[Partner].[Partner].ALLMEMBERS
*
[DimSKU].[XXX Desc].[XXX Desc].ALLMEMBERS
,5
,[Measures].[Actual Retail Value]
) ON ROWS
FROM
(
SELECT
{[DimPartners].[Partner].&[1275]} ON COLUMNS
FROM
(
SELECT
{[Dim Date].[Fiscal Year].&[2014-01-01T00:00:00]} ON COLUMNS
FROM [SALES]
)
)
WHERE
[Dim Date].[Fiscal Year].&[2014-01-01T00:00:00];
You can amend the rows snippet to use the GENERATE function:
SELECT
NON EMPTY
{[Measures].[Actual Retail Value]} ON 0
,NON EMPTY
GENERATE(
[DimBrands].[Brand].[Brand].ALLMEMBERS AS B
,
TopCount(
B.CURRENTMEMBER
*[DimPartners].[Partner].[Partner].ALLMEMBERS
*[DimSKU].[XXX Desc].[XXX Desc].ALLMEMBERS
,5
,[Measures].[Actual Retail Value]
)
) ON ROWS
...
...
This functions usage is detailed here: https://msdn.microsoft.com/en-us/library/ms145526.aspx
I am working on a cross tab query in SQL Server 2008. Everything appear fine apart from this error I am getting.
Here is my code:
select * from
(select ITEM_CODE,NET_PRODUCTION_QUANTITY,RAW_MATERIAL_CODE,DATE_ID from dbo.ODST_PRODUCTION_TRANS
) n
pivot
(sum(NET_PRODUCTION_QUANTITY) for datename(month,DATE_ID) In ([January],[February],[March],[April],[May],[June])) as pvt
where RAW_MATERIAL_CODE = 'X' and DATE_ID between '01-Jan-11' and '30-Jun-11'.
The problem is where the datename(month,date_id) but I can't figure it out. Can anyone give me a solution?
Thanks in advance
I don't think the FOR part of a pivot can be a calculated value at the time of pivot and it must be in your result set.
select * from
(select ITEM_CODE,NET_PRODUCTION_QUANTITY,RAW_MATERIAL_CODE,DATE_ID,datename(month,DATE_ID) as dn from dbo.ODST_PRODUCTION_TRANS
) n
pivot
(sum(NET_PRODUCTION_QUANTITY) for dn In ([January],[February],[March],[April],[May],[June])) as pvt
where RAW_MATERIAL_CODE = 'X' and DATE_ID between '01-Jan-11' and '30-Jun-11'
Try
select * from
(select ITEM_CODE,NET_PRODUCTION_QUANTITY,RAW_MATERIAL_CODE,DATE_ID, datename(month,DATE_ID) as Month from dbo.ODST_PRODUCTION_TRANS
) n
pivot
(
sum(NET_PRODUCTION_QUANTITY)
for Month
In ([January],[February],[March],[April],[May],[June])
) as pvt
where RAW_MATERIAL_CODE = 'X' and DATE_ID between '01-Jan-11' and '30-Jun-11'
I don't think the pivot likes the datename expression, so I've moved it into the query.
it should be like this:
select * from
(select ITEM_CODE,NET_PRODUCTION_QUANTITY,RAW_MATERIAL_CODE,DATE_ID,datename(month,[DATE_ID]) as dtt
from dbo.ODST_PRODUCTION_TRANS) as n
pivot
(
sum(NET_PRODUCTION_QUANTITY)
for [dtt] IN ([January],[February],[March],[April],[May],[June])) as pvt
where RAW_MATERIAL_CODE = 'X' and DATE_ID between '01-Jan-11' and '30-Jun-11'