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,
Related
;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
I am trying to apply ranking to my data set the logic is as follows:
For each ID , Order by ID2 ASC and Order by IsMaster Desc rank the row 1 and only change it when the ID4 value changes
My dataset and desired output looks like:
Test data
CREATE TABLE Test_Table
(ID INT ,ID2 INT, IsMaster INT, ID4 VARCHAR(10))
GO
INSERT INTO Test_Table (ID ,ID2 , IsMaster , ID4 )
VALUES
(1, 101, 1 ,'AAA') -- 1 <-- Desired output for rank
,(1, 102, 0 ,'AAA') -- 1
,(1, 103, 0 ,'AAB') -- 2
,(1, 104, 0 ,'AAB') -- 2
,(1, 105, 0 ,'CCC') -- 3
,(2, 101, 1 ,'AAA') -- 1
,(2, 102, 0 ,'AAA') -- 1
,(2, 103, 0 ,'AAA') -- 1
,(2, 104, 0 ,'AAB') -- 2
,(2, 105, 0 ,'CCC') -- 3
this is what I have tried so far:
SELECT *
,DENSE_RANK() OVER (PARTITION BY ID ORDER BY ID2 ASC, IsMaster DESC ) rn
FROM Test_Table
please please please help me thank you.
This is a island/gap problem.
First you use LAG() to see if you have a different ID4 on the same partition.
Is important you also need partition by IsMaster
Then you create the islands when ID4 changes.
Finally use comulative SUM() to get the proper rank.
Sql Demo
WITH id4_change as (
SELECT *,
LAG(ID4) OVER (PARTITION BY ID, IsMaster ORDER BY ID2) as prev
FROM Test_Table
), islands as (
SELECT *,
CASE WHEN ID4 = PREV
THEN 0
ELSE 1
END as island
FROM id4_change
)
SELECT *,
SUM(island) OVER (PARTITION BY ID, IsMaster ORDER BY ID2) rank
FROM islands
ORDER BY ID, ID2, IsMaster DESC
;
OUTPUT: You can see when ID4 = PREV doesnt create a new "Island" so have same rank.
EDIT: You can simplify first two querys
WITH id4_change as (
SELECT *,
CASE WHEN ID4 = LAG(ID4) OVER (PARTITION BY ID, IsMaster ORDER BY ID2)
THEN 0
ELSE 1
END as island
FROM Test_Table
)
SELECT *,
SUM(island) OVER (PARTITION BY ID, IsMaster ORDER BY ID2) rank
FROM id4_change
ORDER BY ID, ID2, IsMaster DESC
;
Another way probably less efficient but it will work.
WITH X AS
(
SELECT *
,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID2) RowNum
FROM dbo.Test_Table
)
, CTE_VehicleNumber
as
(
SELECT T.ID , T.ID2, t.IsMaster ,T.ID4 , t.RowNum , 1 as [Rank]
FROM X as T
WHERE T.IsMaster = 1
UNION ALL
SELECT T.ID, T.ID2, t.IsMaster ,T.ID4 , t.RowNum , CASE WHEN t.ID4 <> c.ID4 THEN 1+ C.[Rank]
ELSE 0+ C.[Rank]
END as [Rank]
FROM CTE_VehicleNumber as C
inner join X as T ON T.RowNum = C.RowNum + 1
AND t.ID = c.ID
)
SELECT ID , ID2, IsMaster ,ID4 , [Rank]
FROM CTE_VehicleNumber
ORDER BY ID , ID2, IsMaster ,ID4 , [Rank]
OPTION (MAXRECURSION 0);
Are you sure that your orders of ID2 and IsMaster affect the desired result, considering the rest of the data in ID and ID4?
I just tried to use the following code:
; WITH CTE AS (
SELECT DISTINCT ID, ID4, DENSE_RANK() OVER (ORDER BY ID4) Rnk
FROM #Test_Table
)
SELECT t.*, c.Rnk
FROM #Test_Table t
INNER JOIN CTE c ON t.ID = c.ID AND t.ID4 = c.ID4;
... and even with changing the order of ID2 and IsMaster I can't get it to "misbehave" - IF there's only one IsMaster = 1 per a group of ID4's and no duplicates in ID2.
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
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
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]