Retrieving available titles in full outer join of 4 tables - sql

I need to consolidate the output of 4 different attribute tables. All tables have different row count. Currently I have this query:
CREATE VIEW vw_Items
AS
SELECT a.Countryname
,a.Itemname
,ISNULL(a.Colour,'None') as Colour
,ISNULL(b.Location,0) as Location
,ISNULL(c.Size,0) as Size
,ISNULL(d.Weight,0) as Weight
FROM ItemColour a
FULL OUTER JOIN ItemLocation b
ON a.Countryname = b.Countryname
AND a.Itemname= b.Itemname
FULL OUTER JOIN ItemSize c
ON a.Countryname = c.Countryname
AND a.Itemname= c.Itemname
FULL OUTER JOIN ItemWeight d
ON a.Countryname = d.Countryname
AND a.Itemname= d.Itemname
So, the issue is with NULL countryname and Itemname in table a, for which I think I need to do a nested CASE, but is there a better way to handle this?
Thank you.

I suspect you might want:
SELECT ci.Countryname, ci.Itemname
COALESCE(c.Colour, 'None') as Colour,
COALESCE(l.Location, 0) as Location
COALESCE(s.Size, 0) as Size
COALESCE(w.Weight, 0) as Weight
FROM ((SELECT c.countryname, c.itemname
FROM ItemColour c
) UNION -- on purpose to remove duplicates
(SELECT l.countryname, l.itemname
FROM ItemLocation c
) UNION
(SELECT s.countryname, s.itemname
FROM ItemSize
) UNION
(SELECT w.countryname, w.itemname
FROM ItemWeight w
)
) ci LEFT JOIN
ItemColor c
ON c.countryname = ci.countryname AND
c.itemname = ci.itemname LEFT JOIN
ItemLocation l
ON l.countryname = ci.countryname AND
l.itemname = ci.itemname LEFT JOIN
ItemSize s
ON s.countryname = ci.countryname AND
s.itemname = ci.itemname LEFT JOIN
ItemWeight w
ON w.countryname = ci.countryname AND
w.itemname = ci.itemname ;

Related

Left Outer Join returning results to be excluded

I have a query like
WITH a AS ( SELECT *
FROM inventory_tagalongs
WHERE TagAlong_ItemNum <> 'bokiwi2'
)
SELECT inventory.itemnum
, inventory.itemname
, inventory.ItemType,inventory.dept_id
FROM inventory
LEFT OUTER JOIN a
ON inventory.itemnum = a.itemnum
JOIN departments
ON inventory.dept_id = departments.dept_id
JOIN categories
ON departments.subtype = categories.cat_id AND categories.description = 'vapors'
in which i am trying to exclude a's results from the lower syntax but the results return are exactly the same whether or not left outer join..... is there or not.
Do i have my syntax incorrect here?
Good afternoon. Please try this:
select
inventory.itemnum
, inventory.itemname
, inventory.ItemType
, inventory.dept_id
from inventory
join departments on inventory.dept_id=departments.dept_id
join categories on departments.subtype=categories.cat_id and categories.description='vapors'
WHERE NOT EXISTS(
select 1 from inventory_tagalongs B where inventory.itemnum = b.itemnum
AND B.TagAlong_ItemNum <>'bokiwi2');
The CTE overthought the issue a bit. This accomplishes the goal with easier-to-read code and should perform better as well.
Thanks, John.
If you are trying to get results that don't have the tag, your logic is inverted. You want:
SELECT i.itemnum, i.itemname, i.ItemType, i.dept_id
FROM inventory i JOIN
departments d
ON i.dept_id = d.dept_id JOIN
categories c
ON d.subtype = c.cat_id AND
c.description = 'vapors' LEFT OUTER JOIN
a
ON i.itemnum = a.itemnum
WHERE a.itemnum IS NULL;
You don't need a CTE for this at all. It would usually be written as:
WITH a AS (
)
SELECT i.itemnum, i.itemname, i.ItemType, i.dept_id
FROM inventory i JOIN
departments d
ON i.dept_id = d.dept_id JOIN
categories c
ON d.subtype = c.cat_id AND
c.description = 'vapors' LEFT OUTER JOIN
inventory_tagalongs it
ON i.itemnum = it.itemnum AND it.TagAlong_ItemNum = 'bokiwi2'
WHERE a.itemnum IS NULL;
And -- as mentioned in another answer -- NOT EXISTS is another typical way to approach this problem.

Finding the count

I have the following SQL query and need to know the count of companyid as I can see repeating data. How do I find the count of it. Following is the query
SELECT a.companyId 'companyId'
, i.orgDebtType 'orgDebtType'
, d.ratingTypeName 'ratingTypeName'
, c.currentRatingSymbol 'currentRatingSymbol'
, c.ratingStatusIndicator 'ratingStatusIndicator'
, g.qualifierValue 'qualifierValue'
, c.ratingdate 'ratingDate'
, h.value 'outlook'
FROM ciqRatingEntity a
JOIN ciqcompany com
on com.companyId = a.companyId
JOIN ciqratingobjectdetail b ON a.entitySymbolValue = b.objectSymbolValue
JOIN ciqRatingData c ON b.ratingObjectKey = c.ratingObjectKey
JOIN ciqRatingType d ON b.ratingTypeId = d.ratingTypeId
JOIN ciqRatingOrgDebtType i ON i.orgDebtTypeId=b.orgDebtTypeId
JOIN ciqRatingEntityData red ON red.entitySymbolValue=a.entitySymbolValue
AND red.ratingDataItemId='1' ---CoName
LEFT JOIN ciqRatingDataToQualifier f ON f.ratingDataId = c.ratingDataId
LEFT JOIN ciqRatingQualifiervalueType g ON g.qualifiervalueid = f.qualifierValueId
LEFT JOIN ciqRatingValueType h ON h.ratingValueId = c.outlookValueId
WHERE 1=1
AND b.ratingTypeId IN ( '130', '131', '126', '254' )
-- and a.companyId = #companyId
AND a.companyId IN
(SELECT distinct TOP 2000000
c.companyId
FROM ciqCompany c
inner join ciqCompanyStatusType cst on cst.companystatustypeid = c.companystatustypeid
inner join ciqCompanyType ct on ct.companyTypeId = c.companyTypeId
inner join refReportingTemplateType rep on rep.templateTypeId = c.reportingtemplateTypeId
inner join refCountryGeo rcg on c.countryId = rcg.countryId
inner join refState rs on rs.stateId = c.stateId
inner join ciqSimpleIndustry sc on sc.simpleIndustryId = c.simpleIndustryId
ORDER BY companyid desc)
ORDER BY companyId DESC, c.ratingdate, b.ratingTypeId, c.ratingStatusIndicator
This will list where there are duplicate companyID's
SELECT companyId, count(*) as Recs
FROM ciqCompany
GROUP BY ciqCompany
HAVING count(*) > 1
I understand that you wish to add a column to the query with the count of each companyId, you can use COUNT() OVER():
select count(a.companyId) over (partition by a.companyId) as companyCount,
<rest of the columns>
from ciqRatingEntity a
join <rest of the query>
This would return in each row the count of the companyId of that row without grouping the results.

Sum from the different tables Sql server

I have couple of tables which stores amount and I want to group by and get sum - reason for the mutiple tables are nhibernate descriminators.
I am using Union all and works but query is very big.
I am using following query
SELECT CustomerAccountNumber,
vc.CustomerName,
SUM(PermAmount) AS PermAmount,
SUM(FreetextAmount) AS FreetextAmount,
(SUM(PermAmount) + SUM(FreetextAmount)) AS TotalAmountByCustomer
FROM
(
SELECT pp.CustomerAccountNumber,
pl.Amount AS PermAmount,
0 AS FreetextAmount
FROM dbo.PermanentPlacementTransactionLine pl
INNER JOIN dbo.TransactionLine tl ON pl.TransactionLineId = tl.Id
INNER JOIN dbo.PermanentPlacement pp ON pl.PermanentPlacementId = pp.Id
WHERE tl.CurrentStatus = 1
GROUP BY pp.CustomerAccountNumber,
pl.Amount,
tl.Id
UNION ALL
SELECT ft.CustomerAccountNumber,
0 AS PermAmount,
ft.Amount AS FreetextAmount
FROM dbo.FreeTextTransactionLine fttl
INNER JOIN dbo.TransactionLine tl ON fttl.TransactionLineId = tl.Id
INNER JOIN dbo.[FreeText] ft ON fttl.FreeTextId = ft.Id
WHERE tl.CurrentStatus = 1
GROUP BY ft.CustomerAccountNumber,
ft.Amount,
tl.Id
) WIPSummary
INNER JOIN dbo.vw_Customer vc ON WIPSummary.CustomerAccountNumber = vc.CustomerAccount
GROUP BY CustomerAccountNumber,
vc.CustomerName;
is there any elegant way of displaying amount in separate columns ?
I can use partition by if it was same table and want to display row by row.
Try these query, is easy to understand and probably faster than yours.
I assume that the values are unique in your view
WITH cte_a
AS (SELECT pp.customeraccountnumber
,Sum(pl.amount) AS PermAmount
,0 AS FreetextAmount
FROM dbo.permanentplacementtransactionline pl
INNER JOIN dbo.transactionline tl
ON pl.transactionlineid = tl.id
INNER JOIN dbo.permanentplacement pp
ON pl.permanentplacementid = pp.id
WHERE tl.currentstatus = 1
GROUP BY pp.customeraccountnumber),
cte_b
AS (SELECT ft.customeraccountnumber
,0 AS PermAmount
,Sum(ft.amount) AS FreetextAmount
FROM dbo.freetexttransactionline fttl
INNER JOIN dbo.transactionline tl
ON fttl.transactionlineid = tl.id
INNER JOIN dbo.[freetext] ft
ON fttl.freetextid = ft.id
WHERE tl.currentstatus = 1
GROUP BY ft.customeraccountnumber)
SELECT vc.customeraccountnumber
,vc.customername
,Isnull(A.permamount, 0) AS PermAmount
,Isnull(B.freetextamount, 0) AS FreetextAmount
,Isnull(A.permamount, 0)
+ Isnull(B.freetextamount, 0) AS TotalAmountByCustomer
FROM dbo.vw_customer vc
LEFT JOIN cte_a a
ON vc.customeraccount = A.customeraccountnumber
LEFT JOIN cte_b b
ON vc.customeraccount = A.customeraccountnumber
if no table structures and sample data, that is the best I can do to help you.

SQL Filtering rows with no duplicate value

Hi so I'm new to SQL and I'm trying to find a way in which I can obtain only the rows that have values that are not duplicate to each other in a specific column of table.
For example the Table below is called T1 and contains:
ID|Branch ID
1 444
2 333
3 444
4 111
5 555
6 333
The result I want will be
ID|Branch ID
4 111
5 555
So only showing non duplicate rows
Edit: I want to apply this to a large relational code. Here is a snippet of where I want it to be added
FROM dbo.LogicalLine
INNER JOIN dbo.Page ON dbo.LogicalLine.page_id = dbo.Page.id
INNER JOIN dbo.Branch ON dbo.LogicalLine.branch_id = dbo.Branch.id
The table LogicalLine will have a column called branch_id containing duplicate id values. I wish to filter those out showing only the non-duplicate branch_id like above example then INNER JOIN the Branch table into the LogicalLine which I have done.
Added -Full Code here:
SELECT
(SELECT name
FROM ParentDevice
WHERE (Dev1.type NOT LIKE '%cable%') AND (id = Dev1.parent_device_id))T1_DeviceID,
(SELECT name
FROM Symbol
WHERE (id = CP1.symbol_id) AND (type NOT LIKE '%cable%'))T1_DeviceName,
(SELECT name
FROM Location
WHERE (id = Page.location_id))T1_Location,
(SELECT name
FROM Installation
WHERE (id = Page.installation_id))T1_Installation,
(SELECT name
FROM ParentDevice
WHERE (Dev2.type NOT LIKE '%cable%') AND (id = Dev2.parent_device_id))T2_DeviceID,
(SELECT name
FROM Symbol
WHERE ( id = CP2.symbol_id) AND (type NOT LIKE '%cable%'))T2_DeviceName,
(SELECT name
FROM Location
WHERE (id = PD2.location_id))T2_Location,
(SELECT name
FROM Installation
WHERE (id = Page.installation_id))T2_Installation,
(SELECT devicefamily
FROM Device
WHERE (type LIKE '%cable%') AND (id = SymCable.device_id))CablePartNumber,
(SELECT name
FROM ParentDevice
WHERE (id = DevCable.parent_device_id) AND (DevCable.type LIKE '%cable%'))CableTag
FROM dbo.LogicalLine
INNER JOIN dbo.Page ON dbo.LogicalLine.page_id = dbo.Page.id
INNER JOIN dbo.Branch ON dbo.LogicalLine.branch_id = dbo.Branch.id
LEFT OUTER JOIN dbo.Symbol AS SymCable ON dbo.LogicalLine.cable_id = SymCable.id
LEFT OUTER JOIN dbo.Device AS DevCable ON SymCable.device_id = DevCable.id
LEFT OUTER JOIN dbo.ParentDevice AS ParentCable ON DevCable.parent_device_id = ParentCable.id
INNER JOIN dbo.SymbolCP AS CP1 ON dbo.Branch.cp1_id = CP1.id
INNER JOIN dbo.SymbolCP AS CP2 ON dbo.Branch.cp2_id = CP2.id
INNER JOIN dbo.Symbol AS S1 ON CP1.symbol_id = S1.id
INNER JOIN dbo.Symbol AS S2 ON CP2.symbol_id = S2.id
INNER JOIN dbo.Device AS Dev1 ON S1.device_id = Dev1.id
INNER JOIN dbo.Device AS Dev2 ON S2.device_id = Dev2.id
INNER JOIN dbo.ParentDevice AS PD1 ON Dev1.parent_device_id = PD1.id
INNER JOIN dbo.ParentDevice AS PD2 ON Dev2.parent_device_id = PD2.id
INNER JOIN dbo.Location AS L1 ON PD1.location_id = L1.id
INNER JOIN dbo.Location AS L2 ON PD2.location_id = L2.id
INNER JOIN dbo.Installation AS I1 ON L1.installation_id = I1.id
INNER JOIN dbo.Installation AS I2 ON L2.installation_id = I2.id
WHERE
(PD1.project_id = #Projectid) AND (dbo.LogicalLine.drawingmode LIKE '%Single Line%');
Select Id, BranchId from table t
Where not exists
(Select * from table
where id != t.Id
and BranchId = t.BranchId)
or
Select Id, BranchId
From table
Group By BranchId
Having count(*) == 1
EDIT: to modify as requested, simply add to your complete SQL query a Where clause:
Select l.Id BranchId, [plus whatever else you have in your select clause]
FROM LogicalLine l
join Page p ON p.id = l.page_Id
join Branch b ON b.Id = l.branch_id
Group By l.branch_id, [Plus whatever else you have in Select clause]
Having count(*) == 1
or
Select l.Id BranchId, [plus whatever else you have in your select clause]
FROM LogicalLine l
join Page p on p.id = l.page_Id
join Branch b on b.Id = l.branch_id
Where not exists
(Select * from LogicalLine
where id != l.Id
and branch_id = l.branch_id)

Choose the greater of either left or right side of 2 queries

I have the following union query that queries for the most recent date of a column if it exists:
SELECT TOP 1 m.sentdate AS 'calltreelastsignedoff'
FROM Incidents i
INNER JOIN Plans p ON i.planuid = p.uid
INNER JOIN IncidentMessages im ON i.uid = im.incidentuid
INNER JOIN Messages m ON im.messageuid = m.uid
WHERE p.uid = '031E3346-2921-426E-9494-1111111111'
UNION
SELECT TOP 1 m.sentdate AS 'calltreelastsignedoff'
FROM Incidents i
INNER JOIN PlanExercises pe ON i.planexerciseuid = pe.uid
INNER JOIN IncidentMessages im ON i.uid = im.incidentuid
INNER JOIN Messages m ON im.messageuid = m.uid
WHERE pe.planuid = '031E3346-2921-426E-9494-1111111111'
This will return 2 values if each query returns a top 1 result.
What I really want is to select the top 1 of the combined query.
How can I perform a select on the unioned query?
try this:
You could do this with a derived table
select top 1 from
(
SELECT TOP 1 m.sentdate AS 'calltreelastsignedoff'
FROM Incidents i
INNER JOIN Plans p ON i.planuid = p.uid
INNER JOIN IncidentMessages im ON i.uid = im.incidentuid
INNER JOIN Messages m ON im.messageuid = m.uid
WHERE p.uid = '031E3346-2921-426E-9494-1111111111'
UNION
SELECT TOP 1 m.sentdate AS 'calltreelastsignedoff'
FROM Incidents i
INNER JOIN PlanExercises pe ON i.planexerciseuid = pe.uid
INNER JOIN IncidentMessages im ON i.uid = im.incidentuid
INNER JOIN Messages m ON im.messageuid = m.uid
WHERE pe.planuid = '031E3346-2921-426E-9494-1111111111'
)a
order by <col>