How can I get all the rows from master table and relevent row from the detail table in MS-SQL? - vb.net

I am using MS-SQL and I am trying to write a query which fetches rows from the master table and related rows from the detail table. Now, the thing I want is that it must only fetch the first row from the master table and related field from the detail tables should be blank in that first row, now if there are related rows found in the detail tables, they must be shown in the separate rows. I have been trying using the following query but it is not giving the desired result.
SELECT
DISTINCT
ProductMaster.ProductMasterID, ProductMaster.ProductName,
ProductMaster.SubCategoryID, SubCategory.SubCategoryName,
ProductBrandAndType.ProductBranAndTypeID, ProductBrandAndType.ProductType,
ProductBrandAndType.Brand, ProductMaster.ProductDesc,
ProductMaster.ReOrderLevel
FROM
ProductBrandAndType
RIGHT OUTER JOIN
Inward
ON ProductBrandAndType.ProductBranAndTypeID = Inward.ProductBrandAndTypeID
RIGHT OUTER JOIN
ProductMaster
ON Inward.ProductID = ProductMaster.ProductMasterID
LEFT OUTER JOIN
SubCategory
ON ProductMaster.SubCategoryID = SubCategory.SubCategoryID
ORDER BY
ProductMaster.ProductName,
ProductBrandAndType.ProductType,
ProductBrandAndType.Brand;
Can anyone help me on this?
Regards
Sikandar

Following query worked.
SELECT dbo.ProductMaster.ProductMasterID, dbo.ProductMaster.ProductName, dbo.ProductMaster.SubCategoryID, dbo.ProductMaster.ProductDesc,
dbo.ProductMaster.ReOrderLevel, null as ProductBrandAndTypeID,
null AS Type, null as Brand
FROM dbo.ProductBrandAndType RIGHT OUTER JOIN
dbo.Inward ON dbo.ProductBrandAndType.ProductBranAndTypeID = dbo.Inward.ProductBrandAndTypeID RIGHT OUTER JOIN
dbo.ProductMaster ON dbo.Inward.ProductID = dbo.ProductMaster.ProductMasterID LEFT OUTER JOIN
dbo.SubCategory ON dbo.ProductMaster.SubCategoryID = dbo.SubCategory.SubCategoryID
UNION
SELECT dbo.ProductMaster.ProductMasterID, dbo.ProductMaster.ProductName, dbo.ProductMaster.SubCategoryID, dbo.ProductMaster.ProductDesc,
dbo.ProductMaster.ReOrderLevel, dbo.ProductBrandAndType.ProductBranAndTypeID,
dbo.ProductBrandAndType.ProductType, dbo.ProductBrandAndType.Brand
FROM dbo.ProductBrandAndType RIGHT OUTER JOIN
dbo.Inward ON dbo.ProductBrandAndType.ProductBranAndTypeID = dbo.Inward.ProductBrandAndTypeID RIGHT OUTER JOIN
dbo.ProductMaster ON dbo.Inward.ProductID = dbo.ProductMaster.ProductMasterID LEFT OUTER JOIN
dbo.SubCategory ON dbo.ProductMaster.SubCategoryID = dbo.SubCategory.SubCategoryID
ORDER BY ProductName;

If you just what the first row from the ProductMaster. Then you can do something like this:
;WITH CTE
(
SELECT
ROW_NUMBER() OVER(ORDER BY ProductMaster.ProductMasterID) AS RowNbr,
ProductMaster.ProductName,
ProductMaster.SubCategoryID,
ProductMaster.ProductDesc,
ProductMaster.ReOrderLevel
FROM
ProductMaster
)
SELECT
ProductMaster.ProductMasterID,
ProductMaster.ProductName,
ProductMaster.SubCategoryID,
SubCategory.SubCategoryName,
ProductBrandAndType.ProductBranAndTypeID,
ProductBrandAndType.ProductType,
ProductBrandAndType.Brand,
ProductMaster.ProductDesc,
ProductMaster.ReOrderLevel
FROM
ProductBrandAndType
RIGHT OUTER JOIN Inward
ON ProductBrandAndType.ProductBranAndTypeID = Inward.ProductBrandAndTypeID
RIGHT OUTER JOIN CTE AS ProductMaster
ON Inward.ProductID = ProductMaster.ProductMasterID
AND RowNbr=1
LEFT OUTER JOIN SubCategory
ON ProductMaster.SubCategoryID = SubCategory.SubCategoryID
ORDER BY
ProductMaster.ProductName,
ProductBrandAndType.ProductType,
ProductBrandAndType.Brand;

Related

Looking to add in a Count query with Group by INTO an existing working query

Goal:
I wish to get the Count of how many times a WorkItem was re-assigned
From what I understand the proper query is the following:
SELECT
WorkItemDimvw.Id,
COUNT(WorkItemAssignedToUserFactvw.WorkItemAssignedToUser_UserDimKey) AS Assignments
FROM WorkItemDimvw INNER JOIN WorkItemAssignedToUserFactvw
ON WorkItemDimvw.WorkItemDimKey = WorkItemAssignedToUserFactvw.WorkItemDimKey
GROUP BY WorkItemDimvw.Id
The EXISTING query is below and I'm wondering / forgeting if I should:
Just add in COUNT(WorkItemAssignedToUserFactvw.WorkItemAssignedToUser_UserDimKey) AS Assignments since joins are existing, except it is group by WorkItemDimvw.Id
Should it instead be a subquery in the Select below?
Query:
SELECT
SRD.ID,
SRD.Title,
SRD.Description,
SRD.EntityDimKey,
WI.WorkItemDimKey,
IATUFact.DateKey
FROM
SLAConfigurationDimvw
INNER JOIN SLAInstanceInformationFactvw
ON SLAConfigurationDimvw.SLAConfigurationDimKey = SLAInstanceInformationFactvw.SLAConfigurationDimKey
RIGHT OUTER JOIN ServiceRequestDimvw AS SRD
INNER JOIN WorkItemDimvw AS WI
ON SRD.EntityDimKey = WI.EntityDimKey
LEFT OUTER JOIN WorkItemAssignedToUserFactvw AS IATUFact
ON WI.WorkItemDimKey = IATUFact.WorkItemDimKey
AND IATUFact.DeletedDate IS NULL
The trick is to aggregate the data on a sub query, before you join it.
SELECT
SRD.ID,
SRD.Title,
SRD.Description,
SRD.EntityDimKey,
WI.WorkItemDimKey,
IATUFact.DateKey,
IATUFact.Assignments
FROM
SLAConfigurationDimvw
INNER JOIN
SLAInstanceInformationFactvw
ON SLAConfigurationDimvw.SLAConfigurationDimKey = SLAInstanceInformationFactvw.SLAConfigurationDimKey
RIGHT OUTER JOIN
ServiceRequestDimvw AS SRD
ON <you're missing something here>
INNER JOIN
WorkItemDimvw AS WI
ON SRD.EntityDimKey = WI.EntityDimKey
LEFT OUTER JOIN
(
SELECT
WorkItemDimKey,
DateKey,
COUNT(WorkItemAssignedToUser_UserDimKey) AS Assignments
FROM
WorkItemAssignedToUserFactvw
WHERE
DeletedDate IS NULL
GROUP BY
WorkItemDimKey,
DateKey
)
IATUFact
ON WI.WorkItemDimKey = IATUFact.WorkItemDimKey

how to perform Two select query in one stored procedure in sql server

I am trying to perform two select query in one stored procedure. But its not giving me any output. There is no error but records are not being displayed.
First I tried this stored Procedure
CREATE PROCEDURE [dbo].[Sp_PriceList_Die_Wise]
#DieNo As Nvarchar(15),
#MetalCode As Int
AS
BEGIN
Select CP.BatchQty,CP.CastingPrice,U.UNITName As 'Unit',MachPrice,U.UNITName As 'M/C Unit' from CustomerPriceList As CP Left Outer Join UNITMaster As U On CP.MUNITID=U.UNITID where MOULDCODE=#DieNo And METALCODE=#MetalCode
SELECT TOP (10) SubOADetail.OANO, SubOADetail.ID, SubOADetail.QTY, SubOADetail.RATE, UNITMaster.UNITName As Unit, OATest.MachPrices, UNITMaster_1.UNITName AS Unit FROM UNITMaster AS UNITMaster_1 RIGHT OUTER JOIN OATest ON UNITMaster_1.UNITID = OATest.MachUnitID RIGHT OUTER JOIN SubOADetail LEFT OUTER JOIN UNITMaster ON SubOADetail.UNIT = UNITMaster.UNITID ON OATest.ID = SubOADetail.ID AND OATest.OANO = SubOADetail.OANO LEFT OUTER JOIN OADetails ON SubOADetail.OANO = OADetails.OANO WHERE SubOADetail.MOULDCODE = #DieNo AND SubOADetail.METALCODE =#MetalCode ORDER BY OADetails.OADATE DESC
END
This gives me output like this
but I want the output in single table so I created this stored procedure
CREATE PROCEDURE [dbo].[Sp_PriceList_Die_Wise]
#DieNo As Nvarchar(15),
#MetalCode As Int
AS
BEGIN
WITH main AS
(
Select CP.BatchQty,CP.CastingPrice,U.UNITName As 'Unit',
MachPrice,U.UNITName As 'M/C Unit' from CustomerPriceList As CP
Left Outer Join UNITMaster As U On CP.MUNITID=U.UNITID
where MOULDCODE=#DieNo And METALCODE=#MetalCode
), sub AS
(
SELECT TOP (10) SubOADetail.OANO, SubOADetail.ID, SubOADetail.QTY, SubOADetail.RATE,
UNITMaster.UNITName As Unit, OATest.MachPrices, UNITMaster_1.UNITName AS MCUnit
FROM UNITMaster AS UNITMaster_1 RIGHT OUTER JOIN OATest ON UNITMaster_1.UNITID = OATest.MachUnitID
RIGHT OUTER JOIN SubOADetail LEFT OUTER JOIN UNITMaster ON SubOADetail.UNIT = UNITMaster.UNITID
ON OATest.ID = SubOADetail.ID AND OATest.OANO = SubOADetail.OANO LEFT OUTER JOIN OADetails
ON SubOADetail.OANO = OADetails.OANO WHERE SubOADetail.MOULDCODE = #DieNo
AND SubOADetail.METALCODE =#MetalCode ORDER BY OADetails.OADATE DESC
)
SELECT *
FROM main m join sub s
ON m.MachPrice = s.MachPrices
END
But this gives me blank record like this
You are using INNER JOIN, and your first table (main) don't have any records, so you will not get any output.
If you want to select from other table even if matching records are not there in the main, you need to change your JOIN to RIGHT JOIN like following.
SELECT *
FROM main m right join sub s
ON m.MachPrice = s.MachPrices
EDIT:
RIGHT JOIN will work for the provided sample data, in case if you have data where left CTE don't have matching records in right CTE or vise versa and you still want to select the records, for such scenario you need a combination of LEFT JOIN and RIGHT JOIN, for this you can use FULL OUTER JOIN like following.
SELECT *
FROM main m full outer join sub s
ON m.MachPrice = s.MachPrices

SQL Join only if all records have a match

I have 3 tables:
CP_carthead (idOrder)
CP_cartrows (idOrder, idCartRow)
CP_shipping (idCartRow, idShipping, dateShipped)
There can be multiple idCartRows per idOrder.
I want to get all orders where all its idCartRows exist in CP_shipping. This seems like it should be simple, but I haven't found much on the web.
Here's my query now:
SELECT
s.idOrder
, s.LatestDateShipped
FROM
CP_carthead o
LEFT OUTER JOIN (
SELECT
MAX(s.dateShipped) [LatestDateShipped]
, r.idOrder
FROM
CP_shipping s
LEFT OUTER JOIN CP_cartrows r ON s.idCartRow = r.idCartRow
GROUP BY
r.idOrder
) s ON o.idOrder = s.idOrder
Your query is returning rows from "s" and not the orders. Based on your question, I came up with this query:
select o.*
from CP_Carthead o
where o.orderId in (select cr.idOrder
from cp_cartrows cr left outer join
cp_shipping s
on cr.idCartRow = s.IdCartrow
group by cr.idOrder
having count(s.idCartRow) = COUNT(*)
)
The subquery in the in statement is getting orders all of whose cartrows are in shipping.

How can I speed up this view which sums a load of quote line rows?

I am writing a view to show quote totals based on summing the values in a quote line table. I need to restrict the view to only show quotes for customers of a particular 'pricetype'. However when I do this the view slows down a lot.
SQL to sum the prices
SELECT dbo.quoteline.qid, SUM((dbo.pricelist.listprice - dbo.quoteline.voff) * dbo.quoteline.quantity) AS total
FROM dbo.quoteline LEFT OUTER JOIN dbo.pricelist ON dbo.quoteline.prodcode = dbo.pricelist.prodcode GROUP BY dbo.quoteline.qid
SQL once 'pricetype' constraint is added
SELECT dbo.quoteline.qid, SUM((dbo.pricelist.listprice - dbo.quoteline.voff) * dbo.quoteline.quantity) AS total
FROM dbo.pricelist RIGHT OUTER JOIN
dbo.client RIGHT OUTER JOIN
dbo.quote ON dbo.client.cid = dbo.quote.cid RIGHT OUTER JOIN
dbo.quoteline ON dbo.quote.qid = dbo.quoteline.qid ON dbo.pricelist.prodcode = dbo.quoteline.prodcode
WHERE (dbo.client.pricetype = 'V')
GROUP BY dbo.quoteline.qid
Maybe its late and I am having a moment but any help here would be gratefully appreciated.
Two things: First, can you put an index on the dbo.client.pricetype column without it interfering with inserts/updates? Secondly, inner joins are generally faster than outer joins and since your results and where clause depend on the other tables, I suspect you will want to do inner joins anyways unless there are NULL records you need back from your view. Try this following query to see if it gets you the results you need:
SELECT dbo.quoteline.qid, SUM((dbo.pricelist.listprice - dbo.quoteline.voff) * dbo.quoteline.quantity) AS total
FROM dbo.quoteline
INNER JOIN dbo.pricelist ON dbo.quoteline.prodcode = dbo.pricelist.prodcode
INNER JOIN dbo.quote ON dbo.quote.qid = dbo.quoteline.qid
INNER JOIN dbo.client ON dbo.client.cid = dbo.quote.cid
WHERE (dbo.client.pricetype = 'V')
GROUP BY dbo.quoteline.qid
What does happen if you do it like this :
SELECT dbo.quoteline.qid, SUM((dbo.pricelist.listprice - dbo.quoteline.voff) * dbo.quoteline.quantity) AS total
FROM dbo.pricelist RIGHT OUTER JOIN
dbo.client ON dbo.client.pricetype = 'V' RIGHT OUTER JOIN
dbo.quote ON dbo.client.cid = dbo.quote.cid RIGHT OUTER JOIN
dbo.quoteline ON dbo.quote.qid = dbo.quoteline.qid AND dbo.pricelist.prodcode = dbo.quoteline.prodcode
GROUP BY dbo.quoteline.qid

Max date in view on left outer join

Thanks to a previous question, I found out how to pull the most recent data based on a linked table. BUT, now I have a related question.
The solution that I found used row_number() and PARTITION to pull the most recent set of data. But what if there's a possibility for zero or more rows in a linked table in the view? For example, the table FollowUpDate might have 0 rows, or 1, or more. I just want the most recent FollowUpDate:
SELECT
EFD.FormId
,EFD.StatusName
,MAX(EFD.ActionDate)
,EFT.Name AS FormType
,ECOA.Account AS ChargeOffAccount
,ERC.Name AS ReasonCode
,EAC.Description AS ApprovalCode
,MAX(EFU.FollowUpDate) AS FollowUpDate
FROM (
SELECT EF.FormId, EFD.ActionDate, EFS.Name AS StatusName, EF.FormTypeId, EF.ChargeOffId, EF.ReasonCodeId, EF.ApprovalCodeId,
row_number() OVER ( PARTITION BY EF.FormId ORDER BY EFD.ActionDate DESC ) DateSortKey
FROM Extension.FormDate EFD INNER JOIN Extension.Form EF ON EFD.FormId = EF.FormId INNER JOIN Extension.FormStatus EFS ON EFD.StatusId = EFS.StatusId
) EFD
INNER JOIN Extension.FormType EFT ON EFD.FormTypeId = EFT.FormTypeId
LEFT OUTER JOIN Extension.ChargeOffAccount ECOA ON EFD.ChargeOffId = ECOA.ChargeOffId
LEFT OUTER JOIN Extension.ReasonCode ERC ON EFD.ReasonCodeId = ERC.ReasonCodeId
LEFT OUTER JOIN Extension.ApprovalCode EAC ON EFD.ApprovalCodeId = EAC.ApprovalCodeId
LEFT OUTER JOIN (Select EFU.FormId, EFU.FollowUpDate, row_number() OVER (PARTITION BY EFU.FormId ORDER BY EFU.FollowUpDate DESC) FUDateSortKey FROM Extension.FormFollowUp EFU INNER JOIN Extension.Form EF ON EFU.FormId = EF.FormId) EFU ON EFD.FormId = EFU.FormId
WHERE EFD.DateSortKey = 1
GROUP BY
EFD.FormId, EFD.ActionDate, EFD.StatusName, EFT.Name, ECOA.Account, ERC.Name, EAC.Description, EFU.FollowUpDate
ORDER BY
EFD.FormId
If I do a similar pull using row_number() and PARTITION, I get the data only if there is at least one row in FollowUpDate. Kinda defeats the purpose of a LEFT OUTER JOIN. Can anyone help me get this working?
I rewrote your query - you had unnecessary subselects, and used row_number() for the FUDateSortKey but didn't use the column:
SELECT t.formid,
t.statusname,
MAX(t.actiondate) 'actiondate',
t.formtype,
t.chargeoffaccount,
t.reasoncode,
t.approvalcode,
MAX(t.followupdate) 'followupdate'
FROM (
SELECT t.formid,
fs.name 'StatusName',
t.actiondate,
ft.name 'formtype',
coa.account 'ChargeOffAccount',
rc.name 'ReasonCode',
ac.description 'ApprovalCode',
ffu.followupdate,
row_number() OVER (PARTITION BY ef.formid ORDER BY t.actiondate DESC) 'DateSortKey'
FROM EXTENSION.FORMDATE t
JOIN EXTENSION.FORM ef ON ef.formid = t.formid
JOIN EXTENSION.FORMSTATUS fs ON fs.statusid = t.statusid
JOIN EXTENSION.FORMTYPE ft ON ft.formtypeid = ef.formtypeid
LEFT JOIN EXTENSION.CHARGEOFFACCOUNT coa ON coa.chargeoffid = ef.chargeoffid
LEFT JOIN EXTENSION.REASONCODE rc ON rc.reasoncodeid = ef.reasoncodeid
LEFT JOIN EXTENSION.APPROVALCODE ac ON ac.approvalcodeid = ef.approvalcodeid
LEFT JOIN EXTENSION.FORMFOLLOWUP ffu ON ffu.formid = t.formid) t
WHERE t.datesortkey = 1
GROUP BY t.formid, t.statusname, t.formtype, t.chargeoffaccount, t.reasoncode, t.approvalcode
ORDER BY t.formid
The change I made to allow for FollowUpDate was to use a LEFT JOIN onto the FORMFOLLOWUP table - you were doing an INNER JOIN, so you'd only get rows with FORMFOLLOWUP records associated.
It's pretty hard to guess what's going on without table definitions and sample data.
Also, this is confusing: "the table FollowUpDate might have 0 rows" and you "want the most recent FollowUpDate." (especially when there is no table named FollowUpDate) There is no "most recent FollowUpDate" if there are zero FollowUpDates.
Maybe you want
WHERE <follow up date row number> in (1,NULL)
I figured it out. And as usual, I need a nap. I just needed to change my subselect to something I would swear I'd tried with no success:
SELECT field1, field2
FROM Table1 t1
LEFT JOIN (
SELECT field3, max(dateColumn)
FROM Table2
GROUP BY
field3
) t2
ON (t1.field1 = t2.field3)