SQL Join two query results - sql

First SQL Query (Total Memroy)
SELECT
Nodes.NodeID AS NodeID, Nodes.TotalMemory AS TotalMemory, Nodes.Caption AS NodeName
FROM
(Nodes INNER JOIN Volumes ON (Nodes.NodeID = Volumes.NodeID))
Second SQL Query (Number of CPU on nodes)
SELECT N.Caption, COUNT(DISTINCT CPUIndex)
FROM CPUMultiLoad_Detail CPU WITH(NOLOCK)
JOIN Nodes N ON CPU.NodeID = N.NodeID
GROUP BY
N.Caption
Order By
N.Caption
I want to join first query and second query so i have both Total memory and Number of CPU on node in same table. How do i join both query? we can use common key Nodes.NodeID to join but how?

In the general case just use a join and a CTE
WITH PartOne AS
(
SELECT N.NodeID, COUNT(DISTINCT CPU.Index) as [Count]
FROM CPUMultiLoad_Detail CPU WITH(NOLOCK)
JOIN Nodes N ON CPU.NodeID = N.NodeID
GROUP BY N.Caption
)
SELECT Nodes.NodeID
Nodes.TotalMemory ,
Nodes.Caption AS NodeName,
PartOne.[Count]
FROM Nodes
INNER JOIN Volumes ON Nodes.NodeID = Volumes.NodeID
JOIN PartOne ON PartOne.NodeID = Nodes.NodeID
This particular case can also be done in one query like this:
SELECT Nodes.NodeID
Nodes.TotalMemory ,
Nodes.Caption AS NodeName,
COUNT(DISTINCT CPU.Index) OVER (PARTITION BY Nodes.Caption ORDER BY Nodes.Caption) AS [Count]
FROM Nodes
JOIN Volumes ON Nodes.NodeID = Volumes.NodeID
JOIN CPUMultiLoad_Detail CPU ON CPU.NodeID = Nodes.NodeID

For the same situation i used the Temp Table
SELECT ..... FROM.... INTO #Temp1
GO
SELECT ..... FROM.... INTO #Temp2
GO
SELECT ..... FROM #Temp1, #Temp2
WHERE #Temp1.NodeID = #Temp2.NodeID
Remember to Drop the Temp Tables like This:
DROP Table #Temp1
DROP Table #Temp2

"With" comes in help to have a clean query:
WITH CPUOnNodes AS (
SELECT N.NodeID, N.Caption, COUNT(DISTINCT CPUIndex)
FROM CPUMultiLoad_Detail CPU WITH(NOLOCK)
JOIN Nodes N ON CPU.NodeID = N.NodeID
GROUP BY N.NodeID, N.Caption
Order By N.Caption
)
SELECT N.NodeID, N.TotalMemory, N.Caption NodeName
FROM Nodes N
INNER JOIN Volumes V ON N.NodeID = V.NodeID
INNER JOIN CPUOnNodes C ON N.NodeID = C.NodeID

SELECT t1.col2,t2.col3 FROM (SELECT NodeID col1,TotalMemory col2,Caption col3 FROM Nodes)t1 join
(SELECT NodeID col1,Caption col2,COUNT(DISTINCT CPUIndex) col3 FROM CPUMultiLoad_Detail CPU WITH(NOLOCK) GROUP BY Caption Order By Caption)t2 ON t1.col1=t2.col1

Related

SQL Server: JOIN two different queries

sql-server does not have USING function. To join two different tables with multiple select statements we use 'ON' table1.ID = Table2.ID
SELECT *
FROM
(SELECT M.ID as MAPID, M.Name, Avg(Distance) 'Avg Road length', Max(Distance)'Max Length'
FROM MAP
inner join ROAD R on M.ID = R.MapID
GROUP BY M.ID, M.Name) T1
left join
SELECT *
FROM
(SELECT select R.MapID as MAPID, R.IDFrom, R.IDTo
from ROAD R
group by R.MapID, R.IDFrom, R.IDTo) T2 ON T1.MAPID = T2.MAPID
-- using (MAPID); (wrong)
Replace
USING (MAPID)
with
ON t1.mapid = t2.mapid

SQL Join two query

I need some help combining these two queries so I can get this in one single view.
Query 1
select t.*, n.caption, n.description
from (
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 (nolock) where nodeid in (select nodeid from nodesdata)
group by NodeID
) as t
inner join NodesData as n (nolock) on n.nodeid = t.nodeid
where n.description NOT Like '%Windows%'
order by n.description
Query 2
SELECT D.Environment, B.Name, C.Caption, A.ComponentStatisticData, A.ErrorMessage
FROM [APM_CurrentStatistics] A, APM_Application B, NodesData C
join NodesCustomProperties D on D.NodeID= C.NodeID
WHERE
A.ApplicationID=B.ID AND
A.NodeID=C.NodeID AND
B.Name IN ('Oracle Database Licensing')
I want to join first query and second query so I have CPU Information and Licensing Information in same table. How do I join both query? We can use common key Nodes.NodeID to join and not sure how. Any help will be greatly appreciated.
Consider joining the inner aggregate subquery of first query which holds distinct NodeID to the second query using a CTE. Additionally, use explicit JOIN(current standard in SQL) and heed bad habits to kick : using table aliases like (a, b, c) and use more informative table aliases.
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 cp.Environment, app.Name, n.Caption,
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
ORDER BY n.description

Performing a JOIN with the results of a WITH clause

I have one query that uses one join already, call it query1. I would like to join query1 to the results of a WITH clause. I don't know how to merge the two data sets.
Query 1:
SELECT
p.NetObjectID
, n.Caption, n.ObjectSubType
FROM Pollers p
LEFT JOIN NodesData n ON n.NodeID = p.NetObjectID
The next query is a WITH clause. I don't know how to obtain the results without a WITH because I need to do what is outlined in this post.
Query 2:
WITH ranked_DateStamp AS
(
SELECT c.NodeID, c.DateTime
, ROW_NUMBER() OVER (PARTITION BY NodeID ORDER BY DateTime DESC) AS rn
FROM CPULoad AS c
)
SELECT *
FROM ranked_DateStamp
WHERE rn = 1;
I thought I could just JOIN ranked_DateStamp ON ranked_DateStamp.NodeID = p.NodeID but it won't allow it.
You don't really need a with clause here, you can use a subquery. I would just phrase this as:
SELECT
p.NetObjectID,
n.Caption,
n.ObjectSubType,
c.DateTime
FROM Pollers p
LEFT JOIN NodesData n ON n.NodeID = p.NetObjectID
LEFT JOIN (
SELECT
NodeID,
DateTime,
ROW_NUMBER() OVER (PARTITION BY NodeID ORDER BY DateTime DESC) AS rn
FROM CPULoad AS c
) c ON c.rn = 1 and c.NodeID = p.NetObjectID
However, if you were to use a common table expression, that would look like:
WITH ranked_DateStamp AS (
SELECT
NodeID,
DateTime,
ROW_NUMBER() OVER (PARTITION BY NodeID ORDER BY DateTime DESC) AS rn
FROM CPULoad AS c
)
SELECT
p.NetObjectID,
n.Caption,
n.ObjectSubType,
c.DateTime
FROM Pollers p
LEFT JOIN NodesData n ON n.NodeID = p.NetObjectID
LEFT JOIN ranked_DateStamp c ON c.rn = 1 and c.NodeID = p.NetObjectID
Actually, a lateral join might perform equally well, or better:
SELECT
p.NetObjectID,
n.Caption,
n.ObjectSubType,
c.DateTime
FROM Pollers p
LEFT JOIN NodesData n ON n.NodeID = p.NetObjectID
OUTER APPLY (SELECT TOP (1) * FROM CPULOad c WHERE c.NodeID = p.NetObjectID ORDER BY DateTime DESC) c
Actually, I would suggest a different approach -- a lateral join:
SELECT p.NetObjectID, n.Caption, n.ObjectSubType,c.DateTime
FROM Pollers p LEFT JOIN
NodesData n
ON n.NodeID = p.NetObjectID OUTER APPLY
(SELECT TOP (1) NodeID, DateTime,
ROW_NUMBER() OVER (PARTITION BY NodeID ORDER BY DateTime DESC) AS rn
FROM CPULoad c
WHERE c.NodeId = p.NetObjectID
ORDER BY DateTime DESC
) c;
Lateral joins are very powerful and worth learning about. They are also often a bit faster than the ROW_NUMBER() approach.

SQL inner join on alias (for XML)

I have a running query where I need to expand the XML hierarchy.
The existing query does this (WORKING):
select a.fields, (select c.fields from c),
(select d.fields from d), (select e.fields from e)
from a
--REPAIR ORDERS, PARTS, LABOR, NARRATIVE
I need to create another level at b (THIS IS THE JOB ORDER FOR REPAIR ORDERS, and aliased as bb):
--REPAIR ORDERS, JOB ID (JOB ID/PARTS, JOB ID/LABOR, JOB ID/NARRATIVE)
select a.fields, select b.fields, (select c.fields from c),
(select d.fields from d), (select e.fields from e) from b)
bb
from a
so here's the code (this inner join is killing me):
(also, think as REPAIR NARRATIVES as C and once I get this going I need to add D & E)
IT's the INNER JOIN at the comments line which is stopping me:
declare #OEMDEALERCODE nvarchar(20),#SDate smalldatetime,#EDate smalldatetime,#DMxServiceROJobStatus_ReadyToInvoice int
SET #SDate = '01/01/2013'
SET #EDate = '12/31/2013'
SET #DMxServiceROJobStatus_ReadyToInvoice = dbo.[fn_DMxSysGetEnumItemValue](N'DMxServiceROJobStatus', N'ReadyToInvoice')
-- JobId hierarchy
select ff.QualifyingROX, ff.JobId, ff.JobName,
(
---------------------------------------------------------------------------------------------------
SELECT DISTINCT --REPAIR NARRATIVE
Concern, Cause, Correction, CauseMore, ConcernMore, CorrectionMore
FROM
(
SELECT DISTINCT
TOP (100) PERCENT dbo.DMXDEALERINFORMATIONTABLE.OEMDEALERCODE,
dbo.DMXSERVICEROTABLE.ROID,
dbo.DMXSERVICEROJOB.JOBID,
dbo.DMXSERVICEROJOB.STATUS,
DMXSERVICECCCSTATEMENT_1.TEXT CONCERN,
dbo.DMXSERVICECCCSTATEMENT.TEXT CAUSE,
DMXSERVICECCCSTATEMENT_2.TEXT CORRECTION,
dbo.DMXSERVICEROJOB.CUSTOMCAUSETEXT CAUSEMORE,
dbo.DMXSERVICEROJOB.CUSTOMCONCERNTEXT CONCERNMORE,
dbo.DMXSERVICEROJOB.CUSTOMCORRECTIONTEXT CORRECTIONMORE,
DMXSERVICECCCSTATEMENT_2.RECVERSION Expr5,
MAX(dbo.DMXSERVICEROJOB.RECVERSION) Expr4,
MAX(dbo.DMXSERVICECCCSTATEMENT.RECVERSION) Expr3,
MAX(DMXSERVICECCCSTATEMENT_1.RECVERSION) Expr1,
MAX(DMXSERVICECCCSTATEMENT_2.RECVERSION) Expr2
FROM dbo.DMXSERVICEROJOB (NOLOCK) INNER JOIN
dbo.DMXDEALERINFORMATIONTABLE (NOLOCK) INNER JOIN
dbo.DMXSERVICEROTABLE (NOLOCK) ON dbo.DMXDEALERINFORMATIONTABLE.PARTITION = dbo.DMXSERVICEROTABLE.PARTITION ON
dbo.DMXSERVICEROJOB.ROTABLEREF = dbo.DMXSERVICEROTABLE.RECID LEFT OUTER JOIN
dbo.DMXSERVICECCCSTATEMENT DMXSERVICECCCSTATEMENT_2 ON
dbo.DMXSERVICEROJOB.CORRECTIONREF = DMXSERVICECCCSTATEMENT_2.RECID LEFT OUTER JOIN
dbo.DMXSERVICECCCSTATEMENT ON dbo.DMXSERVICEROJOB.CAUSEREF = dbo.DMXSERVICECCCSTATEMENT.RECID LEFT OUTER JOIN
dbo.DMXSERVICECCCSTATEMENT DMXSERVICECCCSTATEMENT_1 ON
dbo.DMXSERVICEROJOB.CONCERNREF = DMXSERVICECCCSTATEMENT_1.RECID
GROUP BY dbo.DMXDEALERINFORMATIONTABLE.OEMDEALERCODE, dbo.DMXSERVICEROTABLE.ROID, dbo.DMXSERVICEROJOB.JOBID, dbo.DMXSERVICEROJOB.STATUS, DMXSERVICECCCSTATEMENT_1.TEXT, dbo.DMXSERVICECCCSTATEMENT.TEXT,
DMXSERVICECCCSTATEMENT_2.TEXT, dbo.DMXSERVICEROJOB.CUSTOMCAUSETEXT, dbo.DMXSERVICEROJOB.CUSTOMCONCERNTEXT,
dbo.DMXSERVICEROJOB.CUSTOMCORRECTIONTEXT, DMXSERVICECCCSTATEMENT_2.RECID, DMXSERVICECCCSTATEMENT_2.PARTITION,
dbo.DMXSERVICECCCSTATEMENT.RECVERSION, dbo.DMXSERVICECCCSTATEMENT.PARTITION, DMXSERVICECCCSTATEMENT_1.PARTITION,
dbo.DMXSERVICEROJOB.RECVERSION, dbo.DMXSERVICEROJOB.RECID, dbo.DMXSERVICEROJOB.PARTITION,
DMXSERVICECCCSTATEMENT_1.RECVERSION, DMXSERVICECCCSTATEMENT_1.RECID, dbo.DMXSERVICECCCSTATEMENT.RECID,
DMXSERVICECCCSTATEMENT_2.RECVERSION
having dbo.DMXDEALERINFORMATIONTABLE.OEMDEALERCODE = #OEMDEALERCODE
--and dbo.DMXSERVICEROTABLE.ROID = ff.QualifyingROX
and dbo.DMXSERVICEROJOB.STATUS=#DMxServiceROJobStatus_ReadyToInvoice
ORDER BY Expr4 DESC, Expr3 DESC, Expr1 DESC, Expr2 DESC
) cc
inner join ff on cc.ROID = ff.QualifyingROX
---------------------------------------------------------------------------------------------------
)
FROM
(
SELECT DISTINCT --REPAIR NARRATIVE
ee.JobId, ee.JobName, ee.QualifyingROX
from
(
SELECT DISTINCT TOP (100) PERCENT
dbo.DMXSERVICEROTABLE.ROID QualifyingROX,
dbo.DMXSERVICEROJOB.JOBID JobId,
MAX(DISTINCT dbo.DMXSERVICEROJOB.NAME) JobName
FROM dbo.DMXSERVICEROTABLE (nolock) INNER JOIN dbo.DMXSERVICEROJOB (NOLOCK) ON dbo.DMXSERVICEROTABLE.RECID = dbo.DMXSERVICEROJOB.ROTABLEREF
GROUP BY dbo.DMXSERVICEROTABLE.ROID, dbo.DMXSERVICEROJOB.JOBID
ORDER BY QualifyingROX, dbo.DMXSERVICEROJOB.JOBID
) ee
) ff
for XML PATH ('JobDetail'), ROOT ('Jobs'), TYPE

What is the correct way to find if any item in a one to many relationship has a flag set?

If I have the following database schema
And I wanted to write a query that listed all Bill_Items, but included a flag that was true if any associated inventory items where marked with the CheckFlag bit, what would be the correct way to do it?
The way I thought of doing it is
select *, case when exists(select CheckFlag
from inventoryitems
inner join Linked_items on Item_code = ItemCode
where Bill_Code = BillCode
and CheckFlag = 1
)
then 1 else 0 end as flagSet
from Bill_items
However I am fairly certain I am not doing this the correct way, what is the way I should be doing a check like this?
Try this:
select
Bill_items.billcode
,max(cast(CheckFlag as int)) as flagSet
from Bill_items
join Linked_items
on Bill_items.billcode = Linked_items.Bill_Code
join inventoryitems
on Linked_items.Item_code = inventoryitems.ItemCode
group by
Bill_items.billcode
If you need to include Bill_items without inventoryitems try this:
select
Bill_items.billcode
,max(isnull(cast(CheckFlag as int),0)) as flagSet
from Bill_items
left join Linked_items
on Bill_items.billcode = Linked_items.Bill_Code
left join inventoryitems
on Linked_items.Item_code = inventoryitems.ItemCode
group by
Bill_items.billcode
Here is a derived version joined onto bill items
select
Bill_items.*
,isnull(_CheckFlags.flagSet,0) as flagSet
from Bill_items
left join (
select
Linked_items.Bill_Code
,max(cast(CheckFlag as int)) as flagSet
from Linked_items
join inventoryitems
on Linked_items.Item_code = inventoryitems.ItemCode
group by
Linked_items.Bill_Code
) _CheckFlags
on Bill_items.billcode = _CheckFlags.Bill_Code
Try this for method without CAST:
select
Bill_items.*
,isnull(_CheckFlags.flagSet,0) as flagSet
from Bill_items
left join (
select
Linked_items.Bill_Code
,CheckFlag as flagSet
from Linked_items
join inventoryitems
on Linked_items.Item_code = inventoryitems.ItemCode
where CheckFlag = 1
group by
Linked_items.Bill_Code
,CheckFlag
) _CheckFlags
on Bill_items.billcode = _CheckFlags.Bill_Code
This should work (the inner sub-query shall save you from adding all the columns in the group by clause) and would also be faster
SELECT
bi.*,
temp.checkflag
FROM
bill_items bi
LEFT JOIN (
SELECT
max(ii.checkflag) as checkflag,
li.bill_code
FROM
linked_items li
JOIN inventory_items ii ON ( ii.item_code = ii.itemCode AND ii.checkflag = 1 )
GROUP BY
li.bill_code
) as temp ON ( temp.bill_code = bi.billCode )
Is there a reason why you don't just join the tables and use a row_number to return the first row for each billcode:
select billcode, flagset
from
(
select b.*, -- replace this with your columns
i.checkflag flagSet,
row_number() over(partition by b.billcode order by i.CheckFlag desc) rn
from Bill_items b
left join Linked_items l
on l.Bill_Code = b.BillCode
left join inventoryitems i
on l.Item_code = i.ItemCode
) d
where rn = 1;
See SQL Fiddle with Demo
The CheckFlag is a bit so the result will be zero or one, there shouldn't be a need for the CASE.