Using Pivot to change Rows into Columns - sql

I am resposting this and adding additional information. I am working on a SQL Query and using Pivot and running into an issue. The columns which I have in the Pivot Table actually show as row data and is repeated for each server.
WITH agg AS
(
select NodeID,
count(distinct cpuindex) as number_of_cpu,
case
when count(distinct cpuindex) < 8 THEN 1
else count(distinct cpuindex) / 8
end AS number_of_cores
from CPUMultiLoad_Detail
where nodeid in (select nodeid from nodesdata)
group by NodeID
)
SELECT * FROM (
SELECT cp.Environment, n.Caption,
cs.ComponentName,cs.ComponentStatisticData, cs.ErrorMessage,
agg.NodeID, agg.number_of_cpu, agg.number_of_cores, n.description
FROM APM_CurrentStatistics cs
INNER JOIN APM_Application app
ON cs.ApplicationID = app.ID
AND app.Name IN ('Oracle Database Licensing')
INNER JOIN NodesData n
ON cs.NodeID = n.NodeID
AND n.description NOT LIKE '%Windows%'
INNER JOIN NodesCustomProperties cp
ON cp.NodeID = n.NodeID
INNER JOIN agg
ON cs.NodeID = agg.NodeID
) t
PIVOT(
max(cs.ErrorMessage) FOR cs.ComponentName IN (
[Oracle Version],
[Oracle Partitioning],
[Oracle Tuning Pack],
[Diagnostic Pack],
[Real Application Clusters (RAC)])
) AS pivot_table;
Desired Output
I am getting this Error
Msg 107, Level 15, State 1, Line 30
The column prefix 'cs' does not match with a table name or alias name used in the query.
Msg 107, Level 15, State 1, Line 30
The column prefix 'cs' does not match with a table name or alias name used in the query.
Any help will be greatly appreciated.

Just take out the two cs. in this line
max(cs.ErrorMessage) FOR cs.ComponentName IN (
It treats the prior select statement like it has already run so those column names don't need to be disambiguated

Related

Querying a cte - The multi-part identifier could not be bound. How do I fix this so I can query the table? New to SQL accounting background

I am trying to extract a dataset which joins 3 tables
Employee E
AbsenceTypes AT
AbsenceBalance AB
In the data set I need the most recent record from AB.BalanceTime for each AB.EmployeeUID by AB.AbsenceTypesUID.
The data set is correct with the output I need, where it fails is when I query the CTE.
;WITH cte AS
(
SELECT TOP (1000)
AB.[UID],
AB.BalanceTime,
AB.AbsenceTypesUID,
AB.Mins,
E.FullName,
E.FirstName, E.LastName,
AB.EmployeeUID,
AT.LongName,
ROW_NUMBER() OVER(PARTITION BY AB.[UID], AB.EmployeeUID ORDER BY AB.BalanceTime DESC) AS RUN
FROM
[RiteqDB].[dbo].[AbsenceBalance] AB
LEFT JOIN
[RiteqDB].[dbo].Employee E ON AB.EmployeeUID = E.UID
LEFT JOIN
[RiteqDB].[dbo].AbsenceTypes AT ON AB.AbsenceTypesUID = AT.UID
)
SELECT *
FROM cte
WHERE RUN = 1 AND E.FullName = 'john citizen'
Error
Msg 4104, Level 16, State 1, Line 45
The multi-part identifier "E.FullName" could not be bound.
I have googled the problem & from what I understand the joined tables do not interact with the CTE which is why it fails with the condition below.
AND E.FullName = 'john citizen'
How can I alter the script so I can query the table?
Table alias E is defined inside the CTE only, not in the outer query. In that scope, there is only one (derived) table, that is called cte, and that has all column names that the CTE returns.
In other words, you can just do:
with cte as (...)
select *
from cte
where run = 1 and fullname = 'john citizen'
If you really want to use aliases, then alias the CTE, and then:
with cte as (...)
select c.*
from cte c
where c.run = 1 and c.fullname = 'john citizen'

Oracle to T-SQL conversion. How can I make this work?

Having trouble converting Oracle syntax to T-SQL. Trying to convert the following statement:
SELECT ORIG.*
,V.COUNTRY_COMMON_NAME
FROM
(SELECT O.*
,LC.LOCAL_COUNCIL
,LC.REGIONAL_COUNCIL
FROM ES_W_ORG_DIM_INIT O
LEFT JOIN ES_W_ORG_DIM_INIT CNTR ON (O.RSC_CNTR_ORG_ID = CNTR.ORG_ID)
LEFT JOIN ES_W_LCL_CNCL_BASE LC ON (TO_CHAR(O.STK_DIST_UNIT_NUMBER) =
TRIM(LC.UNITNUMBER))
WHERE O.ORG_TYPE_ID IN (7,8)
UNION
SELECT O.*
,LC.LOCAL_COUNCIL
,LC.REGIONAL_COUNCIL
FROM ES_W_ORG_DIM_INIT O
LEFT JOIN ES_W_ORG_DIM_INIT CNTR ON (O.RSC_CNTR_ORG_ID = CNTR.ORG_ID)
LEFT JOIN ES_W_LCL_CNCL_BASE LC ON (TO_CHAR(O.UNIT_NUMBER) =
TRIM(LC.UNITNUMBER))
WHERE O.ORG_TYPE_ID IN (5,6)
UNION
SELECT O.*
,NULL AS LOCAL_COUNTCIL
,NULL AS REGIONAL_COUNCIL
FROM ES_W_ORG_DIM_INIT O
WHERE O.ORG_TYPE_ID IN (60,61)
) ORIG
LEFT JOIN DW_ERSDB_ORG_ADDR_VW V ON (ORIG.ORG_ID = V.ORG_ID AND
V.ORG_ADDRESS_TYPE_ID = 1)
Attempted conversion:
WITH ORIG AS(
SELECT O.*
,LC.LOCAL_COUNCIL
,LC.REGIONAL_COUNCIL
FROM DSS_ERS_STAGE.ES_ORG_DIM O
LEFT JOIN DSS_ERS_STAGE.ES_ORG_DIM CNTR ON (O.RSC_CNTR_ORG_ID = CNTR.ORG_ID)
LEFT JOIN DSS_ERS_STAGE.ES_W_LCL_CNCL_BASE LC ON (CONVERT(VARCHAR,
O.STK_DIST_UNIT_NUMBER) = RTRIM(LTRIM(LC.UNITNUMBER)))
WHERE O.ORG_TYPE_ID IN (7,8)
UNION
(SELECT O.*
,LC.LOCAL_COUNCIL
,LC.REGIONAL_COUNCIL
FROM DSS_ERS_STAGE.ES_ORG_DIM O
LEFT JOIN DSS_ERS_STAGE.ES_ORG_DIM CNTR ON (O.RSC_CNTR_ORG_ID = CNTR.ORG_ID)
LEFT JOIN DSS_ERS_STAGE.ES_W_LCL_CNCL_BASE LC ON (CONVERT(VARCHAR,
O.UNIT_NUMBER) = RTRIM(LTRIM(LC.UNITNUMBER)))
WHERE O.ORG_TYPE_ID IN (5,6)
UNION
SELECT O.*
,NULL AS LOCAL_COUNCIL
,NULL AS REGIONAL_COUNCIL
FROM DSS_ERS_STAGE.ES_ORG_DIM O
WHERE O.ORG_TYPE_ID IN (60,61)
))
SELECT ORIG.*, V.COUNTRY_COMMON_NAME
FROM ORIG
LEFT JOIN DSS_ERS_STAGE.DW_ERSDB_ORG_ADDR_VW V ON (ORIG.ORG_ID = V.ORG_ID
AND
V.ORG_ADDRESS_TYPE_ID = 1)
*Just a note that the schemas specified are required in the target database
SQL Server error:
Msg 8156, Level 16, State 1, Line 1
The column 'LOCAL_COUNCIL' was specified multiple times for 'ORIG'.
Any ideas on how I can engineer this to make it work in SQL Server?
Jamie mentioned this in a comment but I'll try to explain in a bit more detail. For purposes of illustration, suppose I have the following two very simple tables.
create table CouncilA (LOCAL_COUNCIL int);
create table CouncilB (LOCAL_COUNCIL int);
insert CouncilA values (1);
insert CouncilB values (1);
SQL Server does allow you to query a result set that has non-unique column names. For instance, the following is legal:
select *
from
CouncilA A
inner join CouncilB B on A.LOCAL_COUNCIL = B.LOCAL_COUNCIL;
It produces the following result set:
LOCAL_COUNCIL LOCAL_COUNCIL
1 1
However, the documentation for common table expressions explicitly states:
Duplicate names within a single CTE definition are not allowed.
So if I try to wrap my earlier query like this, as you've done in your attempted conversion:
with CTE as
(
select *
from
CouncilA A
inner join CouncilB B on A.LOCAL_COUNCIL = B.LOCAL_COUNCIL
)
select * from CTE;
Then I get the error message that you're seeing:
Msg 8156, Level 16, State 1, Line 7
The column 'LOCAL_COUNCIL' was specified multiple times for 'CTE'.
Incidentally, the same is true for a sub-SELECT:
select * from
(
select *
from
CouncilA A
inner join CouncilB B on A.LOCAL_COUNCIL = B.LOCAL_COUNCIL
) X;
Result:
Msg 8156, Level 16, State 1, Line 13
The column 'LOCAL_COUNCIL' was specified multiple times for 'X'.
The error message you see refers to ORIG, which is the name of your CTE, so the definition of that CTE has multiple columns called LOCAL_COUNCIL, which presumably means that your ES_W_ORG_DIM_INIT table has a column called LOCAL_COUNCIL. Make sure your column names are unique within your CTE and you should be okay.

INNER JOINING THE TABLE ITSELF GIVES No column name was specified for column 2

SELECT *
FROM
construction AS T2
INNER JOIN
(
SELECT project,MAX(report_date)
FROM construction
GROUP BY project
) AS R
ON T2.project=R.project AND T2.report_date=R.report_date
getting this error. plz help
No column name was specified for column 2 of 'R'
You need to add alias for MAX(report_date):
SELECT *
FROM construction AS T2
INNER JOIN
(
SELECT project,MAX(report_date) AS report_date
FROM construction
GROUP BY project
) AS R
ON T2.project = R.project
AND T2.report_date = R.report_date;
In SQL Server you can use syntax:
SELECT *
FROM construction AS T2
INNER JOIN
(
SELECT project,MAX(report_date)
FROM construction
GROUP BY project
) AS R(project, report_date)
ON T2.project = R.project
AND T2.report_date = R.report_date;
You should specific the MAX(report_date) with an alias report_date.
Because your table R have two columns project,MAX(report_date).
You are getting this error because you have not specified column name for inner query
You have to write your query as
SELECT *
FROM construction
INNER JOIN
(
SELECT project,MAX(report_date)"Max_ReportDate"
FROM construction
GROUP BY project
) Max_construction
ON construction.project = Max_construction .project
AND construction.report_date = Max_construction .Max_ReportDate

SQL Server 2005 using identifier from previous join statment

I have a table with 2 columns, the first is PKey, the second is an identifier; BAN & IID respectively.
I am looking to pull out the top 2 IID's for every distinct BAN. I used a sub-query in the From to get the Max(IID) which works fine. However when I try to join the table to my 1st statement to get the next highest MAX(IID) I get:
"Msg 4104, Level 16, State 1, Line 1
The multi-part identifier "ii.iid" could not be bound."
This is referring to the Where statement in my 2nd join "where iid < ii.iid"
select distinct ii.BAN, ii.IID, ii2.IID
from (select distinct BAN, IID = Max(IID) from Bill_Timeliness..Invoices with(nolock) group by BAN) II
join (select distinct BAN, IID = Max(IID) from Bill_Timeliness..Invoices with(nolock) where iid < ii.iid group by BAN) II2
on ii.ban = ii2.ban
I have tried re-creating the first part as a second subquery of the where statement.
I also tried where iid < max(ii.iid)
Neither of these worked....i would really appreciate if someone can help me out here.
-Ben
This should work for you:
select o.BAN,
x.MaxID as TopID,
MAX(case when o.IID != x.MaxID then o.IID else null end) as SecondID
from (
select BAN, MAX(IID) as MaxID
from Bill_Timeliness..Invoices group by BAN) x
inner join Bill_Timeliness..Invoices o
on x.BAN = o.BAN
group by o.BAN,
x.MaxID
That is not how aliases are scoped
You could try a CTE instead.
;with CTE_X as (
select BAN, IID, dense_rank() over (partition by BAN order by IID desc) as ranker from Bill_Timeliness..Invoices)
select I.BAN, I.IID, II.IID from CTE_X I inner join CTE_X II on
I.BAN = II.BAN and I.ranker = 1 and II.ranker = 2

getting "No column was specified for column 2 of 'd'" in sql server cte?

I have this query, but its not working as it should,
with c as (select
month(bookingdate) as duration,
count(*) as totalbookings
from
entbookings
group by month(bookingdate)
),
d as (SELECT
duration,
sum(totalitems)
FROM
[DrySoftBranch].[dbo].[mnthItemWiseTotalQty] ('1') AS BkdQty
group by duration
)
select
c.duration,
c.totalbookings,
d.bkdqty
from
c
inner join d
on c.duration = d.duration
when I run this, I am getting
Msg 8155, Level 16, State 2, Line 1
No column was specified for column 2 of 'd'.
Can any one tell me what am I doing wrong?
Also, when I run this,
with c as (select
month(bookingdate) as duration,
count(*) as totalbookings
from
entbookings
group by month(bookingdate)
),
d as (select
month(clothdeliverydate),
SUM(CONVERT(INT, deliveredqty))
FROM
barcodetable
where
month(clothdeliverydate) is not null
group by month(clothdeliverydate)
)
select
c.duration,
c.totalbookings,
d.bkdqty
from
c
inner join d
on c.duration = d.duration
I get
Msg 8155, Level 16, State 2, Line 1
No column was specified for column 1 of 'd'.
Msg 8155, Level 16, State 2, Line 1
No column was specified for column 2 of 'd'.
You just need to provide an alias for your aggregate columns in the CTE
d as (SELECT
duration,
sum(totalitems) as sumtotalitems
FROM
[DrySoftBranch].[dbo].[mnthItemWiseTotalQty] ('1') AS BkdQty
group by duration
)
[edit]
I tried to rewrite your query, but even yours will work once you associate aliases to the aggregate columns in the query that defines 'd'.
I think you are looking for the following:
First one:
select
c.duration,
c.totalbookings,
d.bkdqty
from
(select
month(bookingdate) as duration,
count(*) as totalbookings
from
entbookings
group by month(bookingdate)
) AS c
inner join
(SELECT
duration,
sum(totalitems) 'bkdqty'
FROM
[DrySoftBranch].[dbo].[mnthItemWiseTotalQty] ('1') AS BkdQty
group by duration
) AS d
on c.duration = d.duration
Second one:
select
c.duration,
c.totalbookings,
d.bkdqty
from
(select
month(bookingdate) as duration,
count(*) as totalbookings
from
entbookings
group by month(bookingdate)
) AS c
inner join
(select
month(clothdeliverydate) 'clothdeliverydatemonth',
SUM(CONVERT(INT, deliveredqty)) 'bkdqty'
FROM
barcodetable
where
month(clothdeliverydate) is not null
group by month(clothdeliverydate)
) AS d
on c.duration = d.duration
I had a similar query and a similar issue.
SELECT
*
FROM
Users ru
LEFT OUTER JOIN
(
SELECT ru1.UserID, COUNT(*)
FROM Referral r
LEFT OUTER JOIN Users ru1 ON r.ReferredUserId = ru1.UserID
GROUP BY ru1.UserID
) ReferralTotalCount ON ru.UserID = ReferralTotalCount.UserID
I found that SQL Server was choking on the COUNT(*) column, and was giving me the error No column was specified for column 2.
Putting an alias on the COUNT(*) column fixed the issue.
SELECT
*
FROM
Users ru
LEFT OUTER JOIN
(
SELECT ru1.UserID, COUNT(*) AS -->MyCount<--
FROM Referral r
LEFT OUTER JOIN Users ru1 ON r.ReferredUserId = ru1.UserID
GROUP BY ru1.UserID
) ReferralTotalCount ON ru.UserID = ReferralTotalCount.UserID
A single with clause can introduce multiple query names by separating them with a comma but it's mandatory that every column has a name
In this case, the second query has a column without one:
as (SELECT
duration,
sum(totalitems) --**HERE IS A MISSING NAME**
FROM ...
That's all.
Because you are creatin a table expression, you have to specify the structure of that table, you can achive this on two way:
1: In the select you can use the original columnnames (as in your first example), but with aggregates you have to use an alias (also in conflicting names). Like
sum(totalitems) as bkdqty
2: You need to specify the column names rigth after the name of the talbe, and then you just have to take care that the count of the names should mach the number of coulms was selected in the query. Like:
d (duration, bkdqty)
AS (Select.... )
With the second solution both of your query will work!
Quite an intuitive error message - just need to give the columns in d names
Change to either this
d as
(
select
[duration] = month(clothdeliverydate),
[bkdqty] = SUM(CONVERT(INT, deliveredqty))
FROM
barcodetable
where
month(clothdeliverydate) is not null
group by month(clothdeliverydate)
)
Or you can explicitly declare the fields in the definition of the cte:
d ([duration], [bkdqty]) as
(
select
month(clothdeliverydate),
SUM(CONVERT(INT, deliveredqty))
FROM
barcodetable
where
month(clothdeliverydate) is not null
group by month(clothdeliverydate)
)
Just add an alias name as follows
sum(totalitems) as totalitems.
evidently, as stated in the parser response, a column name is needed for both cases. In either versions the columns of "d" are not named.
in case 1: your column 2 of d is sum(totalitems) which is not named. duration will retain the name "duration"
in case 2: both month(clothdeliverydate) and SUM(CONVERT(INT, deliveredqty)) have to be named
Msg 8155, Level 16, State 2, Line 1
No column was specified for column 1 of 'd'.
Msg 8155, Level 16, State 2, Line 1
No column was specified for column 2 of 'd'.
ANSWER:
ROUND(AVG(CAST(column_name AS FLOAT)), 2) as column_name