Related
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,
;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 need some thoughts to the best implementation of this case
I have data where there can be multiple values with start & end datetime, now i need to pull the data without overlapping the dates, below is the sample data.
CREATE TABLE table2 (
start_date DATE NOT NULL,
end_date DATE NOT NULL,
comments VARCHAR(100) NULL ,
id int
);
INSERT INTO table2 (start_date, end_date, id) VALUES
('2011-12-01', '2012-01-02', 5),
('2012-01-01', '2012-01-06', 5),
('2012-01-05', '2012-01-10', 5),
('2012-01-09', '2012-01-11', 5);
from this i need the data which is not overlapping for each id
('2011-12-01', '2012-01-02', 5),
('2012-01-05', '2012-01-10', 5)
Please share me the thoughts on what cane be the best way to implement this ?
Thanks for the support
Thanks,
Manoj.
The output you provide is very unclear. On the first sight you are looking for an intervall, where not other intervall starts within (which would lead to a continued intervall). But your second expected line is overlapping with 2012-01-10?
The following query will return a row, if its end_date is not within another rows intervall... But this does not return your two expected rows, just the first.
SELECT * FROM table2 AS t
WHERE NOT EXISTS(SELECT 1
FROM table2 AS x
WHERE x.start_date<>t.start_date
AND x.end_date BETWEEN t.start_date AND t.end_date
);
I hope this points you the right direction...
The following will do it:
WITH cte
AS
(
SELECT
[start_date]
, end_date
, comments
, id
FROM
(
SELECT
[start_date]
, end_date
, comments
, id
, ROW_NUMBER() OVER (PARTITION BY id ORDER BY [start_date]) R
FROM table2
) Q
WHERE R = 1
UNION ALL
SELECT
[start_date]
, end_date
, comments
, id
FROM
(
SELECT
T.[start_date]
, T.end_date
, T.comments
, T.id
, ROW_NUMBER() OVER (PARTITION BY T.id ORDER BY T.[start_date]) R
FROM
cte C
JOIN table2 T ON
C.id = T.id
AND T.[start_date] > C.end_date
) Q
WHERE R = 1
)
SELECT
[start_date]
, end_date
, comments
, id
FROM cte
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