Mandt Specified Multiple Times But Not in Query - sql

I get this error
Msg 8156, Level 16, State 1, Line 67
The column 'MANDT' was specified multiple times for 'cte'."
when attempting to run the code below however I am not including the column MANDT in my query. Both tables that I am calling do have a column MANDT, but they both have the column STAT as well and I did not have a problem with another table attempting the same join, the only thing is that table did not have MANDT, only STAT was the same.
I attempted to include both columns MANDT with an alias: JCDS_SOGR.MANDT as Client and TJ30T.MANDT as Client2 separately and together, this did not pan out. Got the same error message.
;WITH cte AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY STAT ORDER BY UDATE) AS Rn,
*,
LAG(UDATE) OVER (PARTITION BY STAT ORDER BY UDATE) AS PrevUDate,
COUNT(*) OVER (PARTITION BY STAT) AS [Count]
FROM
JCDS_SOGR
JOIN
TJ30T on JCDS_SOGR.STAT = TJ30T.ESTAT
WHERE
OBJNR = 'IE000000000010003137'
)
SELECT
MAX(rn) AS [Count],
OBJNR, STAT, TXT30,
SUM(CASE
WHEN rn % 2 = 0
THEN DATEDIFF(d, PrevUDate, UDATE)
WHEN rn = [Count]
THEN DATEDIFF(d, UDATE, GETDATE())
ELSE 0
END) AS DIF
FROM
cte
GROUP BY
OBJNR, STAT, TXT30
This is the other query I referred to that works fine with this same code.
;with cte
AS
(
select ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as Rn
, *
, LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate
, COUNT(*) OVER(partition by STAT) As [Count]
from JCDS_SOGR
join TJ02T on JCDS_SOGR.STAT = TJ02T.ISTAT
where OBJNR = 'IE000000000010003137'
and TJ02T.SPRAS = 'E'
)
select Max(rn) As [Count]
, OBJNR,STAT,TXT30
, SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE)
WHEN rn=[Count] THEN DATEDIFF(d,UDATE,getDate())
ELSE 0 END) as DIF
from cte
group BY OBJNR, STAT,TXT30
The expected result is this
[COUNT OBJNR STAT TXT30 DIF
1 IE000000000010003137 I0099 Available 2810][1]

In your CTE, you are selecting *. So if you have two columns named MANDT, this could cause a conflict. Remove *. That should fix the problem that you described.

Related

WITH Clause Syntax error - While using Outer select

I have created a sql which is below, when i am trying to put this under outer select which will l just display the results that are rendered from below WITH clause query it is giving me error in sql server, where as working fine with Oracle.
I don't want to create a view i want to put this below ouptut in merge statement...
select custno, slipno, category, donation, unique_nm from
(
-- Here it is throwing error
with got_debit_custno (custno, slipno, category, donation, debit_custno) as
(
select custno, slipno, category, donation
, case
when category = 'CREDIT'
then 'N/A'
else custno
end
from a
)
, prep (custno, slipno, category, donation, debit_custno, rn, rdt) as
(
select dc.*
, row_number () over (partition by debit_custno, category order by donation, slipno)
, sum (donation) over (partition by debit_custno, category order by donation, slipno)
from got_debit_custno dc
)
, r (custno, slipno, category, donation, debit_custno, rn, rdt, mn) as
(
select custno, slipno, category, donation, debit_custno
, case
when rn = max(rn) over (partition by debit_custno, category)
then rn
end
, rdt, 1
from prep
where rdt <= 27000 or rn = 1
union all
select p.custno, p.slipno, p.category, p.donation, p.debit_custno
, case
when p.rn = max(p.rn) over (partition by p.debit_custno, p.category)
then p.rn
end
, p.rdt, r.mn + 1
from prep p
join r on p.debit_custno = r.debit_custno
and p.category = r.categoRy
and p.rn > r.rn
and (p.rdt <= r.rdt + 27000 or p.rn = r.rn + 1)
)
select custno, slipno, category, donation
, dense_rank () over (order by debit_custno, category, mn) as unique_nm
from r)
order by custno, unique_nm, donation
WITH must be the first keyword of the query. The previous statement must be be terminated by ; as:
;WITH got_debit_custno (custno, slipno, category, donation, debit_custno) as
(
select custno, slipno, category, donation
, case
when category = 'CREDIT'
then 'N/A'
else custno
end
from a
)
, prep (custno, slipno, category, donation, debit_custno, rn, rdt) as
(
select dc.*
, row_number () over (partition by debit_custno, category order by donation, slipno)
, sum (donation) over (partition by debit_custno, category order by donation, slipno)
from got_debit_custno dc
)
, r (custno, slipno, category, donation, debit_custno, rn, rdt, mn) as
(
select custno, slipno, category, donation, debit_custno
, case
when rn = max(rn) over (partition by debit_custno, category)
then rn
end
, rdt, 1
from prep
where rdt <= 27000 or rn = 1
union all
select p.custno, p.slipno, p.category, p.donation, p.debit_custno
, case
when p.rn = max(p.rn) over (partition by p.debit_custno, p.category)
then p.rn
end
, p.rdt, r.mn + 1
from prep p
join r on p.debit_custno = r.debit_custno
and p.category = r.categoRy
and p.rn > r.rn
and (p.rdt <= r.rdt + 27000 or p.rn = r.rn + 1)
)
select custno, slipno, category, donation
, dense_rank () over (order by debit_custno, category, mn) as unique_nm
from r
order by custno, unique_nm, donation

How to get the validity date range of a price from individual daily prices in SQL

I have some prices for the month of January.
Date,Price
1,100
2,100
3,115
4,120
5,120
6,100
7,100
8,120
9,120
10,120
Now, the o/p I need is a non-overlapping date range for each price.
price,from,To
100,1,2
115,3,3
120,4,5
100,6,7
120,8,10
I need to do this using SQL only.
For now, if I simply group by and take min and max dates, I get the below, which is an overlapping range:
price,from,to
100,1,7
115,3,3
120,4,10
This is a gaps-and-islands problem. The simplest solution is the difference of row numbers:
select price, min(date), max(date)
from (select t.*,
row_number() over (order by date) as seqnum,
row_number() over (partition by price, order by date) as seqnum2
from t
) t
group by price, (seqnum - seqnum2)
order by min(date);
Why this works is a little hard to explain. But if you look at the results of the subquery, you will see how the adjacent rows are identified by the difference in the two values.
SELECT Lag.price,Lag.[date] AS [From], MIN(Lead.[date]-Lag.[date])+Lag.[date] AS [to]
FROM
(
SELECT [date],[Price]
FROM
(
SELECT [date],[Price],LAG(Price) OVER (ORDER BY DATE,Price) AS LagID FROM #table1 A
)B
WHERE CASE WHEN Price <> ISNULL(LagID,1) THEN 1 ELSE 0 END = 1
)Lag
JOIN
(
SELECT [date],[Price]
FROM
(
SELECT [date],Price,LEAD(Price) OVER (ORDER BY DATE,Price) AS LeadID FROM [#table1] A
)B
WHERE CASE WHEN Price <> ISNULL(LeadID,1) THEN 1 ELSE 0 END = 1
)Lead
ON Lag.[Price] = Lead.[Price]
WHERE Lead.[date]-Lag.[date] >= 0
GROUP BY Lag.[date],Lag.[price]
ORDER BY Lag.[date]
Another method using ROWS UNBOUNDED PRECEDING
SELECT price, MIN([date]) AS [from], [end_date] AS [To]
FROM
(
SELECT *, MIN([abc]) OVER (ORDER BY DATE DESC ROWS UNBOUNDED PRECEDING ) end_date
FROM
(
SELECT *, CASE WHEN price = next_price THEN NULL ELSE DATE END AS abc
FROM
(
SELECT a.* , b.[date] AS next_date, b.price AS next_price
FROM #table1 a
LEFT JOIN #table1 b
ON a.[date] = b.[date]-1
)AA
)BB
)CC
GROUP BY price, end_date

Select a line equal to 'X' without TOP 'N' plus the previous line 'Y' in SQL Server?

I need to return in a query only the last lines with 'ProductStatus' equal 'Stop' and the previous line.
I have the table:
And need to get this result:
How do I do this in SQL Server?
One method uses window functions to calculate the last stop and then get the row before that:
select t.*
from (select t.*,
lead(seqnum_ps) over (partition by producttype order by datevalue) as next_seqnum_ps,
lead(status) over (partition by producttype order by datevalue) as next_status
from (select t.*,
row_number() over (partition by producttype, product_status order by datevalue desc) as seqnum_ps
from t
) t
) t
where (seqnum_ps = 1 and product_status = 'Stop') or
(next_seqnum_ps = 1 and next_product_status = 'Stop');
An alternative method gets the maximum stop time and uses that:
select t.*
from (select t.*,
max(case when product_status = 'Stop' then datevalue end) over (partition by producttype) as max_stop_dv,
lead(datevalue) over (partition by producttype order by datevalue) as next_dv
from t
) t
where datevalue = max_stop_dv or
next_dv = max_stop_dv;

Perform a Series of Calculations on a Multiple CTE Table

Can't seem to figure out the formula for performing a series of functions on my query. I need to subtract the figures in the DIF column depending on the STAT code. I need to perform the same series of functions in every case. STAT I0099 MINUS E0002, this result will always be the denominator. After this I need to take each of the other lines in the table and divide them by this result.
1st (2811-98), 2nd E0013 (52/(2811-98)) 3rd E0019 (405/(2811-98)) 4th E0004 (2256/(2811-98) End.
I've tried adding rollup and a couple of others things, I saw on here, but none were successful.
WITH i_stat_cte
AS
(
SELECT ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as
Rn,JCDS_SOGR.OBJNR, JCDS_SOGR.STAT,JCDS_SOGR.UDATE,JCDS_SOGR.CHGNR,JCDS_SOGR.CDTCODE,JCDS_SOGR.CHIND,JCDS_SOGR.INACT,JCDS_SOGR.TCODE,TJ02T.TXT30, EQUI.BAUJJ as "Year", T370K_T.EARTX as Model,
LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate,
COUNT(*) OVER(partition by STAT) As [Count]
from JCDS_SOGR
Join TJ02T on JCDS_SOGR.STAT = TJ02T.ISTAT
Join EQUI on JCDS_SOGR.OBJNR = EQUI.OBJNR
Join T370K_T on equi.EQART = T370K_T.EQART
where jcds_sogr.OBJNR = 'IE000000000010003137'
and TJ02T.SPRAS = 'E'
)
,
e_stat_cte
AS
(
SELECT ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as Rn, JCDS_SOGR.OBJNR, JCDS_SOGR.STAT,JCDS_SOGR.UDATE,JCDS_SOGR.CHGNR,JCDS_SOGR.CDTCODE,JCDS_SOGR.CHIND,JCDS_SOGR.INACT,JCDS_SOGR.TCODE,TJ30T.TXT30, EQUI.BAUJJ as "Year", T370K_T.EARTX as Model,
LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate,
COUNT(*) OVER(partition by STAT) As [Count], TJ30T.MANDT as Client
from JCDS_SOGR
Join TJ30T on JCDS_SOGR.STAT = TJ30T.ESTAT
Join EQUI on JCDS_SOGR.OBJNR = EQUI.OBJNR
Join T370K_T on equi.EQART = T370K_T.EQART
where jcds_sogr.OBJNR = 'IE000000000010003137'
and TJ30T.SPRAS = 'E'AND TJ30T.MANDT='400'
AND TJ30T.STSMA = 'VEHICLE' AND T370K_T.MANDT = '400')
SELECT Max(rn) As [Count],
OBJNR,Year, Model, STAT,TXT30,
SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE)
WHEN rn=[Count] THEN DATEDIFF(d,UDATE,getDate())
ELSE 0 END) as DIF
from i_stat_cte
Group BY OBJNR, STAT,TXT30, Year, Model
UNION
SELECT Max(rn) As [Count],
OBJNR,Year, Model, STAT,TXT30,
SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE)
WHEN rn=[Count] THEN DATEDIFF(d,UDATE,getDate())
ELSE 0 END) as DIF
from e_stat_cte
Group BY OBJNR, STAT,TXT30, Year, Model
EXPECTED RESULTS
Count OBJNR Year Model STAT TXT30 DIF Avail | Calculations
1 IE000000000010003137 2011 Orion I0099 Avail 2810
2 IE000000000010003137 2011 Orion E0002 Await 98
4 IE000000000010003137 2011 Orion E0013 Non Op 52 .0191740 = (52/(2810-98))
4 IE000000000010003137 2011 Orion E0019 OperBk 405 .1493363 = (405/(2810-98))
7 IE000000000010003137 2011 Orion E0004 Oper 2255 .8314897 = (2255/(2810-98))
--The code below is a conversion of your code from CTE to temp tables.
--Hopefully you can perform better diagnostics on it. Just evaluate each of the data you are producing on your last query. I think the UNION is a bit sloppy. Are you sure it's really a UNION and not a UNION ALL?
DROP TABLE IF EXISTS #i_stat_cte
SELECT ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as
Rn,JCDS_SOGR.OBJNR, JCDS_SOGR.STAT,JCDS_SOGR.UDATE,JCDS_SOGR.CHGNR,JCDS_SOGR.CDTCODE,JCDS_SOGR.CHIND,JCDS_SOGR.INACT,JCDS_SOGR.TCODE,TJ02T.TXT30, EQUI.BAUJJ as "Year", T370K_T.EARTX as Model,
LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate,
COUNT(*) OVER(partition by STAT) As [Count]
INTO #i_stat_cte
from JCDS_SOGR
Join TJ02T on JCDS_SOGR.STAT = TJ02T.ISTAT
Join EQUI on JCDS_SOGR.OBJNR = EQUI.OBJNR
Join T370K_T on equi.EQART = T370K_T.EQART
where jcds_sogr.OBJNR = 'IE000000000010003137'
and TJ02T.SPRAS = 'E'
DROP TABLE IF EXISTS #e_stat_cte
SELECT ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as Rn, JCDS_SOGR.OBJNR, JCDS_SOGR.STAT,JCDS_SOGR.UDATE,JCDS_SOGR.CHGNR,JCDS_SOGR.CDTCODE,JCDS_SOGR.CHIND,JCDS_SOGR.INACT,JCDS_SOGR.TCODE,TJ30T.TXT30, EQUI.BAUJJ as "Year", T370K_T.EARTX as Model,
LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate,
COUNT(*) OVER(partition by STAT) As [Count], TJ30T.MANDT as Client
INTO #e_stat_cte
from JCDS_SOGR
Join TJ30T on JCDS_SOGR.STAT = TJ30T.ESTAT
Join EQUI on JCDS_SOGR.OBJNR = EQUI.OBJNR
Join T370K_T on equi.EQART = T370K_T.EQART
where jcds_sogr.OBJNR = 'IE000000000010003137'
and TJ30T.SPRAS = 'E'AND TJ30T.MANDT='400'
AND TJ30T.STSMA = 'VEHICLE' AND T370K_T.MANDT = '400'
-- VERIFY YOU GET WHAT YOU EXPECT
select * from #i_stat_cte
-- VERIFY YOU GET WHAT YOU EXPECT
select * from #e_stat_cte
-- VERIFY YOU GET WHAT YOU EXPECT
SELECT Max(rn) As [Count],
OBJNR,Year, Model, STAT,TXT30,
SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE)
WHEN rn=[Count] THEN DATEDIFF(d,UDATE,getDate())
ELSE 0 END) as DIF
from #i_stat_cte
Group BY OBJNR, STAT,TXT30, Year, Model
--UNION
-- VERIFY YOU GET WHAT YOU EXPECT
SELECT Max(rn) As [Count],
OBJNR,Year, Model, STAT,TXT30,
SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE)
WHEN rn=[Count] THEN DATEDIFF(d,UDATE,getDate())
ELSE 0 END) as DIF
from #e_stat_cte
Group BY OBJNR, STAT,TXT30, Year, Model

SQL Query to get percentages of two selects?

I currently use two seperate Queries to recieve lists of total runs and lists of errors, so i use excel to divide these numbers to get percentages.
The problem is, that i use a subselect to get the errors, because i group the first select, and therefore cannot use the conditions in the first.
So my Query to get all runs is:
Select
Count(*) as All, year([US-Date]) as year, month([US-Date]) as month, day([US-Date]) as day
FROM
(Select
ROW_NUMBER() OVER (PARTITION BY Int_No ORDER BY Time desc) AS RowNumber, [US-Date]
FROM
dbo.Mydatabase
Where
[US-Date] between '2017-10-01' and '2018-03-01') AS a
WHERE
a.RowNumber = 1
GROUP BY
year([US-Date]), month([US-Date]), day([US-Date])
ORDER BY
year([US-Date]), month([US-Date]), day([US-Date])
which gives me a list of all testruns for each day.
then i use this Query to get the errors:
Select
Count(*) as fejlende, year([US-Date]) as år,
month([US-Date]) as måned, day([US-Date]) as dag
From
(Select
ROW_NUMBER() OVER (PARTITION BY Int_No ORDER BY Time desc) AS RowNumber, [US-Date]
From
dbo.Mydatabase
Where
[US-Date] between '2017-10-01' and '2018-03-01'
and ErrorCode in
(Select
ErrorCode from dbo.Mydatabase
Where
(ErrorCode like '2374' or ErrorCode like '2373' or ErrorCode like '2061'))) AS a
WHERE
a.RowNumber = 1
GROUP BY
year([US-Date]), month([US-Date]), day([US-Date])
ORDER BY
year([US-Date]), month([US-Date]), day([US-Date])
So my question is: can i make one query that finds both lists, and divide them, so i dont have to put them into excel and so on :-)?
You can use a CASE expression for this (I simplified the errorcode check):
Select COUNT(*) as ALL
, COUNT(CASE WHEN ErrorCode IN ('2374', '2373', '2061') THEN 1 END) AS fejlende
, YEAR([US-Date]) as year
, MONTH([US-Date]) as month
, DAY([US-Date]) as day
from (
Select ROW_NUMBER() OVER (PARTITION BY Int_No ORDER BY Time desc) AS RowNumber, [US-Date]
From dbo.Mydatabase
Where [US-Date] between '2017-10-01' and '2018-03-01') AS a
where a.RowNumber = 1
GROUP BY year([US-Date]), month([US-Date]), day([US-Date])
ORDER BY year([US-Date]), month([US-Date]), day([US-Date])
Something like this??
SELECT
Count(*) as [Total],
SUM(CASE WHEN (ErrorCode like '2374' or ErrorCode like '2373' or ErrorCode like '2061') THEN 1 ELSE 0 END) AS Errors,
year([US-Date]) as [Year],
month([US-Date]) as [Month],
day([US-Date]) as [Day]
FROM dbo.Mydatabase
WHERE ROW_NUMBER() OVER (PARTITION BY Int_No ORDER BY Time desc) = 1
AND [US-Date] between '2017-10-01' and '2018-03-01'
GROUP BY year([US-Date]), month([US-Date]), day([US-Date])
ORDER BY year([US-Date]), month([US-Date]), day([US-Date])
Not really sure what your ROW_NUMBER is used for, but hopefully you get the idea and can adopt to your needs now you know the SUM(CASE WHEN) method?