MS Access Query to SQL Server Transform And Pivots - sql-server

I need to Convert Access Query to SQL Sever Query.
qry_BudgetForTwelveMonths :
SELECT t.JobId, t.AccountId, t.FinancialYear AS FinYear, t.Period, Sum(t.Amount) AS Amt
FROM (SELECT JobId, AccountId,FinancialYear, Period, Amount FROM Temp_BlankBudgets
union all
SELECT JobId, AccountId,FinancialYear, Period, Amount FROM Temp_Budgets) AS t
GROUP BY t.JobId, t.AccountId, t.Period, t.FinancialYear
ORDER BY t.JobId, t.AccountId, t.Period;
Qry_CrstabJobBudgetForTwelveMonths :
TRANSFORM Sum(qry_BudgetForTwelveMonths.Amt) AS SumOfAmt
SELECT qry_BudgetForTwelveMonths.JobId, qry_BudgetForTwelveMonths.AccountId, qry_BudgetForTwelveMonths.FinYear, Sum(qry_BudgetForTwelveMonths.Amt) AS FYTotal
FROM qry_BudgetForTwelveMonths
GROUP BY qry_BudgetForTwelveMonths.JobId, qry_BudgetForTwelveMonths.AccountId, qry_BudgetForTwelveMonths.FinYear
PIVOT qry_BudgetForTwelveMonths.Period;
Final Query
SELECT Temp_Accounts.AccountNumber, Temp_Accounts.AccountName,Qry_CrstabJobBudgetForTwelveMonths.[1],Qry_CrstabJobBudgetForTwelveMonths.[2], Qry_CrstabJobBudgetForTwelveMonths.[3],Qry_CrstabJobBudgetForTwelveMonths.[4], Qry_CrstabJobBudgetForTwelveMonths.[5],
Qry_CrstabJobBudgetForTwelveMonths.[6], Qry_CrstabJobBudgetForTwelveMonths.[7],
Qry_CrstabJobBudgetForTwelveMonths.[8], Qry_CrstabJobBudgetForTwelveMonths.[9],
Qry_CrstabJobBudgetForTwelveMonths.[10], Qry_CrstabJobBudgetForTwelveMonths.[11],
Qry_CrstabJobBudgetForTwelveMonths.[12], Temp_Accounts.AccountID,Qry_CrstabJobBudgetForTwelveMonths.FYTotal
FROM Temp_Accounts INNER JOIN Qry_CrstabJobBudgetForTwelveMonths ON
Temp_Accounts.AccountID = Qry_CrstabJobBudgetForTwelveMonths.AccountID

Here's my take:
--qry_BudgetForTwelveMonths :
SELECT
t.JobId
, t.AccountId
, t.FinancialYear AS FinYear
, t.Period
, Sum(t.Amount) AS Amt
INTO #tmp1
FROM (SELECT
JobId
, AccountId
,FinancialYear
, Period
, Amount
FROM Temp_BlankBudgets
union all
SELECT
JobId
, AccountId
,FinancialYear
, Period
, Amount
FROM Temp_Budgets) AS t
GROUP BY t.JobId, t.AccountId, t.Period, t.FinancialYear
ORDER BY t.JobId, t.AccountId, t.Period;
--Qry_CrstabJobBudgetForTwelveMonths :
SELECT *
INTO #tmp2
FROM (
SELECT
a.JobId
, a.AccountId
, a.FinancialYear
, Sum(a.Amount) AS FYTotal
FROM #tmp a
GROUP BY a.JobId, a.AccountId, a.FinancialYear
) AS SOURCE
PIVOT
(
Sum(a.Amount) AS SumOfAmt
FOR BMonth IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) AS PVT
ORDER BY BMonth
--Final Query
SELECT
Temp_Accounts.AccountNumber
, Temp_Accounts.AccountName
, b.[1]
, b.[2]
, b.[3]
, b.[4]
, b.[5]
, b.[6]
, b.[7]
, b.[8]
, b.[9]
, b.[10]
, b.[11]
, b.[12]
, Temp_Accounts.AccountID
, b.FYTotal
FROM Temp_Accounts
INNER JOIN #tmp2 b
ON Temp_Accounts.AccountID = b.AccountID

Related

Display date in the column depending on certain conditions

While running the below code, I am getting the error:
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression
when I add the last bit of code (see after union)
(select top 1 convert(varchar,PaymentDate,103) from tblUTRDetail where CCN_No=CR.CCN_NO and CR.Claim_Status='Y' order by PaymentDate desc
union all
select top 1 convert(varchar,CreatedDate,103) from tblOpenCloseTrans where S_NO=CR.S_NO and OpenCloseType='C' and CR.Claim_Status='C' order by CreatedDate desc
union all
select top 1 convert(varchar,GENERATED_DATE,103) from tbldeficiencyletterTrans where S_NO=CR.S_NO and DEFICIENT_REPUDATION_FLAG='NC' and CR.Claim_Status='NC' order by GENERATED_DATE desc
union all
select top 1 convert(varchar,GENERATED_DATE,103) from tbldeficiencyletterTrans where S_NO=CR.S_NO and DEFICIENT_REPUDATION_FLAG='R' and CR.Claim_Status='RC' order by GENERATED_DATE desc
union
(select GENERATED_DATE from (Select s_no, convert (varchar,(GENERATED_DATE),103)as GENERATED_DATE ,row_number()
over(partition by s_no order by s_no asc )as rw from tblDeficiencyLetterTrans b
where DEFICIENT_REPUDATION_FLAG='NC' and s_no=CR.S_NO) T where rw=1)
)
as SETTLEMENT_DATE,
create table #tempT (Material varchar(10),yyyyww int,item_type varchar(10),TPT int )
-------------Insert---------------
insert into #tempT values('E123' , 201919 , 'Assembly' , 7)
insert into #tempT values('E123' , 201919 , 'Assembly' , 6)
insert into #tempT values('E123' , 201919 , 'Assembly' , 7)
insert into #tempT values('E123' , 201919 , 'Assembly' , 7)
insert into #tempT values('E123' , 201919 , 'FG' , 2)
insert into #tempT values('E123' , 201919 , 'FG' , 2)
insert into #tempT values('E123' , 201919 , 'FG' , 1)
insert into #tempT values('E123' , 201919 , 'TEST' , 7)
insert into #tempT values('E123' , 201919 , 'TEST' , 4)
------------Output-------------
select Material ,ceiling(((sum((MaxTPT)))/7.00)+1)MaxTPT
from(select Material,item_type,case when item_type='Assembly' then max(TPT)
when item_type='fg' then max(TPT)
when item_type='TEST' then max(TPT) end MaxTPT from #tempT
group by Material,item_type)a`enter code here`
group by Material
Your query looks like this:
SELECT *
,(select 1 union all select 2
union all select 3
union all select 3
union (select 4)) as SETTLEMENT_DATE
FROM sys.tables
You are selecting some columns values and the for one of them you can return up to 4 values for one column SETTLEMENT_DATE.
So, you can have multiple values where one value is expected and this is what the error is saying to you. You have to options:
if you want to see all values, just give a separated name to each column like this
SELECT *
,select 1 as SETTLEMENT_DATE1
,
select 2 as SETTLEMENT_DATE2
,
select 3 as SETTLEMENT_DATE3
,
select 3 as SETTLEMENT_DATE4
,
(select 4) as SETTLEMENT_DATE5
FROM sys.tables
add more logic to return only one value each time from this sub-query
(
SELECT TOP 1 date
FROM
(
(select top 1 convert(varchar,PaymentDate,103) from tblUTRDetail where CCN_No=CR.CCN_NO and CR.Claim_Status='Y' order by PaymentDate desc
union all
select top 1 convert(varchar,CreatedDate,103) from tblOpenCloseTrans where S_NO=CR.S_NO and OpenCloseType='C' and CR.Claim_Status='C' order by CreatedDate desc
union all
select top 1 convert(varchar,GENERATED_DATE,103) from tbldeficiencyletterTrans where S_NO=CR.S_NO and DEFICIENT_REPUDATION_FLAG='NC' and CR.Claim_Status='NC' order by GENERATED_DATE desc
union all
select top 1 convert(varchar,GENERATED_DATE,103) from tbldeficiencyletterTrans where S_NO=CR.S_NO and DEFICIENT_REPUDATION_FLAG='R' and CR.Claim_Status='RC' order by GENERATED_DATE desc
union
(select GENERATED_DATE from (Select s_no, convert (varchar,(GENERATED_DATE),103)as GENERATED_DATE ,row_number()
over(partition by s_no order by s_no asc )as rw from tblDeficiencyLetterTrans b
where DEFICIENT_REPUDATION_FLAG='NC' and s_no=CR.S_NO) T where rw=1)
)
) DS (date)
ORDER BY date
)
as SETTLEMENT_DATE,

Multi - Columns OVERLAPPING DATES

;with cte as (
select Domain_Id, Starting_Date, End_Date
from Que_Date
union all
select t.Domain_Id, cte.Starting_Date, t.End_Date
from cte
join Que_Date t on cte.Domain_Id = t.Domain_Id and cte.End_Date = t.Starting_Date),
cte2 as (
select *, rn = row_number() over (partition by Domain_Id, End_Date order by Domain_Id)
from cte
)
select DISTINCT Domain_Id, Starting_Date, max(End_Date) enddate
from cte2
where rn=1
group by Domain_Id, Starting_Date
order by Domain_Id, Starting_Date;
select * from Que_Date
This is the code that I have wrote but i am getting an extra row i.e 2nd row is extra, the expected output should have only 1st, 3rd and 4th row as output so please help me with it.
I have attached an image showing Input, Excepted Output, and the output that I am getting.
You've got so many results in your first cte. Your first cte has consisting domains. So you cannot filter domains based on your cte. So you query has unnecessary rows.
Try this solution. Cte ConsistentDomains has just consistent domains. So based on this cte, we can get not overlapped results.
Create and fill data:
CREATE TABLE FooTable
(
Domain_ID INT,
Starting_Date DATE,
End_Date Date
)
INSERT INTO dbo.FooTable
(
Domain_ID,
Starting_Date,
End_Date
)
VALUES
( 1, -- Domain_ID - int
CONVERT(datetime,'01-01-2011',103), -- Starting_Date - date
CONVERT(datetime,'05-01-2011',103) -- End_Date - date
)
, (1, CONVERT(datetime,'05-01-2011',103), CONVERT(datetime,'07-01-2011',103))
, (1, CONVERT(datetime,'07-01-2011',103), CONVERT(datetime,'15-01-2011',103))
, (2, CONVERT(datetime,'11-05-2011',103), CONVERT(datetime,'12-05-2011',103))
, (2, CONVERT(datetime,'13-05-2011',103), CONVERT(datetime,'14-05-2011',103))
Query to find not overlapping results:
DECLARE #startDate varchar(50) = '2011-01-01';
WITH ConsistentDomains AS
(
SELECT
f.Domain_ID
, f.Starting_Date
, f.End_Date
FROM FooTable f
WHERE f.Starting_Date = #startDate
UNION ALL
SELECT
s.Domain_ID
, s.Starting_Date
, s.End_Date
FROM FooTable s
INNER JOIN ConsistentDomains cd
ON s.Domain_ID = cd.Domain_ID
AND s.Starting_Date = cd.End_Date
), ConsistentDomainsRownumber AS
(
SELECT
cd.Domain_ID
, cd.Starting_Date
, cd.End_Date
, ROW_NUMBER() OVER (PARTITION BY cd.Domain_ID ORDER BY cd.Starting_Date,
cd.End_Date) RN
FROM ConsistentDomains cd
)
SELECT cd.Domain_ID
, convert(varchar, cd.Starting_Date, 105) Starting_Date
, convert(varchar, cd.End_Date, 105) End_Date
FROM ConsistentDomainsRownumber cd WHERE cd.RN = 1
UNION ALL
SELECT
ft.Domain_ID
, convert(varchar, ft.Starting_Date, 105) Starting_Date
, convert(varchar, ft.End_Date, 105) End_Date
FROM dbo.FooTable ft WHERE ft.Domain_ID NOT IN (SELECT cd.Domain_ID FROM
ConsistentDomainsRownumber cd)
Output:
I used the same table creating script as provided by #stepup, but you can also get your outcome in this way.
CREATE TABLE testtbl
(
Domain_ID INT,
Starting_Date DATE,
End_Date Date
)
INSERT INTO testtbl
VALUES
(1, convert(date, '01-01-2011' ,103), convert(date, '05-01-2011',103) )
,(1, convert(date, '05-01-2011' ,103), convert(date, '07-01-2011',103) )
,(1, convert(date, '07-01-2011' ,103), convert(date, '15-01-2011',103) )
,(2, convert(date, '11-05-2011' ,103), convert(date, '12-05-2011',103) )
,(2, convert(date, '13-05-2011' ,103), convert(date, '14-05-2011',103) )
You can make use of self join and Firs_value and last value within the group to make sure that you are comparing within the same ID and overlapping dates.
select distinct t.Domain_ID,
case when lag(t1.starting_date)over (partition by t.Domain_id order by
t.starting_date) is not null
then first_value(t.Starting_Date) over (partition by t.domain_id order by
t.starting_date)
else t.Starting_Date end StartingDate,
case when lead(t.domain_id) over (partition by t.domain_id order by t.starting_date) =
t1.Domain_ID then isnull(last_value(t.End_Date) over (partition by t.domain_id order by t.end_date rows between unbounded preceding and unbounded following),t.End_Date)
else t.End_Date end end_date
from testtbl t
left join testtbl t1 on t.Domain_ID = t1.Domain_ID
and t.End_Date = t1.Starting_Date
and t.Starting_Date < t1.Starting_Date
Output:
Domain_ID StartingDate end_date
1 2011-01-01 2011-01-15
2 2011-05-11 2011-05-12
2 2011-05-13 2011-05-14

Find Non Consecutive date in SQL Server

I want to find the missing NON-consecutive dates between two consecutive date.
I am posting my SQL query and temp tables to find out the results.
But I am not getting the proper results
Here is my SQL Query
drop table #temp
create table #temp(an varchar(20),dt date)
insert into #temp
select '2133783715' , '2016-10-16' union all
select '5107537880' , '2016-10-15' union all
select '6619324250' , '2016-10-15' union all
select '7146586717' , '2016-10-15' union all
select '7472381321' , '2016-10-12' union all
select '7472381321' , '2016-10-13' union all
select '7472381321' , '2016-10-14' union all
select '7472381321' , '2016-10-24' union all
select '8186056340' , '2016-10-15' union all
select '9099457123' , '2016-10-12' union all
select '9099457123' , '2016-10-13' union all
select '9099457123' , '2016-10-14' union all
select '9099457123' , '2016-10-23' union all
select '9099457123' , '2016-11-01' union all
select '9099457123' , '2016-11-02' union all
select '9099457123' , '2016-11-03' union all
select '9165074784' , '2016-10-16'
drop table #final
SELECT an,MIN(dt) AS MinDate,MAX(dt) AS MaxDate, COUNT(*) AS ConsecutiveUsage
--DateDiff(Day,LAG(MAX(dt)) OVER (partition by an ORDER BY an),MAX(dt)) nonusageDate
into #final
FROM(
SELECT an,dt,
DATEDIFF(D, ROW_NUMBER() OVER(partition by an ORDER BY dt),dt) AS Diff
FROM #temp c
)P
GROUP BY an,diff
select * from #final order by 1
an MinDate MaxDate ConsecutiveUsage
2133783715 2016-10-16 2016-10-16 1
5107537880 2016-10-15 2016-10-15 1
6619324250 2016-10-15 2016-10-15 1
7146586717 2016-10-15 2016-10-15 1
7472381321 2016-10-12 2016-10-14 3
7472381321 2016-10-24 2016-10-24 1
7472381321 2016-10-27 2016-10-28 1
8186056340 2016-10-15 2016-10-15 1
9099457123 2016-10-12 2016-10-14 3
9099457123 2016-10-23 2016-10-23 1
9165074784 2016-10-16 2016-10-16 1
But I want results of non-usage date.
I want to get those AN which has not been used continuously since 10 days.
So here output should be like this:-
an minusagesdate maxusagedate ConsecutiveNotUseddays
7472381321 2016-10-15 2016-10-23 9
7472381321 2016-10-25 2016-10-26 2
9099457123 2016-10-15 2016-10-22 8
So I just want to find out only consecutive not used dates count and their min and max dates .
try this :
with ranked as (
select f1.*,
ROW_NUMBER() over(partition by an order by dt) rang
from #temp f1
where exists
(select * from #temp f2
where f1.an=f2.an and datediff( day, f2.dt, f1.dt) >1
)
)
select an, minusagesdate, maxusagesdate, ConsecutiveNotUseddays
from (
select f1.*,
DATEADD(DAY,1, (select f2.dt from ranked f2 where f1.an=f2.an and f2.rang+1=f1.rang)) minusagesdate ,
DATEADD(DAY,-1, f1.dt) maxusagesdate ,
datediff( day, (select f2.dt from ranked f2 where f1.an=f2.an and f2.rang+1=f1.rang), f1.dt) - 1 ConsecutiveNotUseddays
from ranked f1
) tmp
where tmp.ConsecutiveNotUseddays>0
or like this
with ranked as (
select f1.*,
ROW_NUMBER() over(partition by an order by dt) rang
from #temp f1
where exists
(select * from #temp f2
where f1.an=f2.an and datediff( day, f2.dt, f1.dt) >1
)
)
select f1.an,
DATEADD(DAY,1, f3.dtbefore) minusagesdate ,
DATEADD(DAY,-1, f1.dt) maxusagesdate ,
datediff( day, f3.dtbefore, f1.dt) - 1 ConsecutiveNotUseddays
from ranked f1
outer apply
(
select top 1 f2.dt as dtbefore from ranked f2
where f1.an=f2.an and f2.rang+1=f1.rang
) f3
where datediff( day, f3.dtbefore, f1.dt) - 1>0
It looks like you're trying to count the number of days not used between the mindate and the maxdate for each an. If that's the case, then this should do the trick:
select an, min(dt) as min_dt, max(dt) as max_dt
, count(distinct dt) as daysused --this counts each day used, but only once
, datediff(day,min(dt),max(dt)) as totaldays --this is the total number of days between min and max date
, datediff(day,min(dt),max(dt)) - count(distinct dt) as daysnotused
--This takes total days - used days to give non-used days
from #temp c
group by an
having datediff(day,min(dt),max(dt)) - count(distinct dt) >= 10
As I understood you need this:
;WITH cte AS (
SELECT an,
dt,
ROW_NUMBER() OVER (PARTITION BY an ORDER BY dt) as rn
FROM #temp
)
SELECT c1.an,
c1.dt MinDate,
c2.dt MaxDate,
DATEDIFF(day,c1.dt,c2.dt) as ConsecutiveNotUseddays
FROM cte c1
INNER JOIN cte c2
ON c1.an = c2.an AND c1.rn = c2.rn-1
WHERE DATEDIFF(day,c1.dt,c2.dt) >= 10
Output:
an MinDate MaxDate ConsecutiveNotUseddays
7472381321 2016-10-14 2016-10-24 10
For 9099457123 I got two rows with 9 in ConsecutiveNotUseddays. You can check results removing WHERE statement.
On any newer version of SQL Server this should be easy:
with x as (
select *, lag(dt) over(partition by an order by dt) dt_lag
from #temp
)
select *, datediff(day, dt_lag, dt)
from x
where datediff(day, dt_lag, dt) >= 10

Repeat the first date withing a group

I Would like the first date of each group to repeat for the rest of the rows withing each group
You could use window expressions and grouping;
FIRST_VALUE (Transact-SQL)
You would need to partition by your first column. to get the split of A and B.
For example;
with cteTempData
(
[Code]
, [Date]
)
as
(
select 'A',cast('2015-9-4' as date)
union all select 'A','2015-9-4'
union all select 'A','2015-9-4'
union all select 'A','2015-9-16'
union all select 'B','2015-9-16'
union all select 'B','2015-9-22'
union all select 'B','2015-9-22'
union all select 'B','2015-10-26'
union all select 'B','2015-10-30'
)
select
[Code]
, [Date]
, FIRST_VALUE([Date]) over (partition by [Code] order by [Date]) as [First_Date]
from cteTempData
Using the first_value syntax also allows you to work with other columns in that ordered record....
with cteTempData
(
[Code]
, [Date]
, [Comment]
)
as
(
select 'A',cast('2015-9-4' as date),'One'
union all select 'A','2015-9-4','Two'
union all select 'A','2015-9-4','Three'
union all select 'A','2015-9-16','Four'
union all select 'B','2015-9-16','Five'
union all select 'B','2015-9-22','Six'
union all select 'B','2015-9-22','Seven'
union all select 'B','2015-10-26','Eight'
union all select 'B','2015-10-30','Nine'
)
select
[Code]
, [Date]
, FIRST_VALUE([Date]) over (partition by [Code] order by [Date]) as [First_Date]
, FIRST_VALUE([Comment]) over (partition by [Code] order by [Date]) as [First_Comment]
from cteTempData
Use MIN() Over ()
Declare #Table table (Grp varchar(25),Date date)
Insert into #Table values
('A','2015-09-04'),
('A','2015-09-05'),
('A','2015-09-10'),
('B','2015-10-04'),
('B','2015-10-05'),
('B','2015-10-10')
Select *
,GrpDate = min(Date) over (Partition By Grp)
From #Table
Returns
Grp Date GrpDate
A 2015-09-04 2015-09-04
A 2015-09-05 2015-09-04
A 2015-09-10 2015-09-04
B 2015-10-04 2015-10-04
B 2015-10-05 2015-10-04
B 2015-10-10 2015-10-04
You could use MIN with the OVER-clause
SELECT t.ColumnA,
DateCol = MIN( t.DateCol ) OVER ( PARTITION BY t.ColumnA ),
OtherColumns
FROM dbo.TableName t
you can go with a CROSS JOIN or FIRST_VALUE.
Declare #Yourtable table (groupCol varchar(25),firstDate date)
Insert into #Yourtable values
('A','2015-09-04'),
('A','2015-09-05'),
('A','2015-09-10'),
('B','2015-10-04'),
('B','2015-10-05'),
('B','2015-10-10')
SELECT a.*,b.firstDate
FROM #Yourtable a
CROSS JOIN (SELECT groupCol,MIN(firstDate) firstDate
FROM #Yourtable b
GROUP BY groupCol)b
WHERE a.groupCol =b.groupCol
OR
SELECT a.*,FIRST_VALUE(a.firstDate) OVER (PARTITION BY groupCol ORDER BY groupCol ASC) AS firstDate
FROM #Yourtable a

Add values from one column into another column

I have such query:
SELECT
CurrentAccountID
, IncomeBYR + IncomeConvertBYR AS AmountBYR
, IncomeUSD AS AmountUSD
, [Date] AS ExecutionDate
FROM CTE2
ORDER BY [Date]
I need to combine AmountBYR and AmountUSD into one column with the same dates.
Result set is something like:
CurrentAccountID AmountTotal ExecutionDate
3 2383410.00 2010-02-13
3 -159 2010-02-13
... .... .....
Is exist some way to do it in one Select query?
I would use a UNION ALL.
Something like
SELECT
CurrentAccountID
, IncomeBYR + IncomeConvertBYR AS AmountTotal
, [Date] AS ExecutionDate
FROM CTE2
UNION ALL
SELECT
CurrentAccountID
, IncomeUSD AS AmountTotal
, [Date] AS ExecutionDate
FROM CTE2
ORDER BY [Date]

Resources