Grab all rows for a Records where a single instance occurs in a different row for the record - sql

I have a query where I am looking into three different tables and for the purposes of this post I only need to see three columns; RecordID, FieldType and Tranid. The Record ID can have multiple Field types and each field type will have a distinct tranid.
What I am trying to do is grab all the entire set of data if any of the Field Types = 'CO'
SELECT
Header.RecordID,
Detail.FieldType,
Header.TranID
FROM Header
INNER JOIN (select * from Detail where fieldtype = 'CO') as Detail
ON Header.RecordID = Detail.RecordID
INNER JOIN TranDef ON Header.TranID = TranDef.TranID
WHERE
(Header.CalendarDate BETWEEN GETDATE() - 10 AND GETDATE())
But this is not working. I'm only getting one row of data back, where as I said, I want all the data for the record, not just the one row. What am I doing wrong here?

Your query does not work because it limits the rows selected from Detail to these with fieldtype = 'CO', and inner joins to it.
It looks like you are looking for a WHERE EXISTS query:
SELECT
h.RecordID,
d.FieldType,
h.TranID
FROM
Branch b
INNER JOIN
Header h ON b.BranchID = h.BranchID
INNER JOIN
Detail d ON h.RecordID = d.RecordID
WHERE (h.CalendarDate BETWEEN GETDATE() - 10 AND GETDATE())
AND EXISTS (
SELECT *
FROM Detail dd
WHERE dd.RecordID = h.RecordID AND dd.fieldtype = 'CO'
)
The idea is to join to all Detail records, and then filter the result based on existence or non-existence of 'CO' records among the Detail rows linked to the corresponding Header row.

You can try including the below in the WHERE criteria:
SELECT RecordID, FieldType, TranID
FROM Branch br, Header hr, Region rgn
WHERE br.FieldType = 'CO' and
hr.FieldType = 'CO' and
rgn.FieldType = 'CO'

I feel like your making this more complicated than it should be. Perhaps try the following? I know I've done similiar things in the past.
SELECT
h.RecordID,
d.FieldType,
h.TranID
FROM Header as h
INNER JOIN Branch as b on b.BranchID = h.BranchID
INNER JOIN Detail as d on d.RecordID = h.RecordID
WHERE
(h.CalendarDate BETWEEN GETDATE() - 10 AND GETDATE())
and d.fieldtype = 'CO'

Related

Display Y/N column if record found in detail table

I'm trying to create a query so that I can have a column show Y/N if a particular item was ordered for a group of orders. The item I'm looking for would be OLI.id = '538'.
So my results would be:
Order#, Customer#, FreightPaid
12345, 00112233, Y
12346, 00112233, N
I cannot figure out if I need to use a subquery or the where exists function ?
Here's my current query:
SELECT distinct
OrderID,
Accountuid as Customerno
FROM [SMILEWEB_live].[dbo].[OrderLog] OL
inner join Orderlog_item OLI on OLI.orderlogkey = OL.[key]
inner join Account A on A.uid = OL.Accountuid
where A.GroupId = 'X9955'
and OL.CreateDate >= GETDATE() - 60
I would suggest an exists clause instead of a join:
select ol.OrderID, ol.Accountuid as Customerno,
(case when exists (select 1
from Orderlog_item OLI join
Account A
on A.uid = OL.Accountuid
where OLI.orderlogkey = OL.[key] and A.GroupId = 'X9955'
)
then 1 else 0
end) as flag
from [SMILEWEB_live].[dbo].[OrderLog] OL
where OL.CreateDate >= GETDATE() - 60;
This prevents a couple of problems. First, duplicate rows which are caused when there are multiple matching rows (and select distinct add unnecessary overhead). Second, missing rows, which happen when you use inner join instead of an outer join.

How can I join on multiple columns within the same table that contain the same type of info?

I am currently joining two tables based on Claim_Number and Customer_Number.
SELECT
A.*,
B.*,
FROM Company.dbo.Company_Master AS A
LEFT JOIN Company.dbp.Compound_Info AS B ON A.Claim_Number = B.Claim_Number AND A.Customer_Number = B.Customer_Number
WHERE A.Filled_YearMonth = '201312' AND A.Compound_Ind = 'Y'
This returns exactly the data I'm looking for. The problem is that I now need to join to another table to get information based on a Product_ID. This would be easy if there was only one Product_ID in the Compound_Info table for each record. However, there are 10. So basically I need to SELECT 10 additional columns for Product_Name based on each of those Product_ID's that are being selected already. How can do that? This is what I was thinking in my head, but is not working right.
SELECT
A.*,
B.*,
PD_Info_1.Product_Name,
PD_Info_2.Product_Name,
....etc {Up to 10 Product Names}
FROM Company.dbo.Company_Master AS A
LEFT JOIN Company.dbo.Compound_Info AS B ON A.Claim_Number = B.Claim_Number AND A.Customer_Number = B.Customer_Number
LEFT JOIN Company.dbo.Product_Info AS PD_Info_1 ON B.Product_ID_1 = PD_Info_1.Product_ID
LEFT JOIN Company.dbo.Product_Info AS PD_Info_2 ON B.Product_ID_2 = PD_Info_2.Product_ID
.... {Up to 10 LEFT JOIN's}
WHERE A.Filled_YearMonth = '201312' AND A.Compound_Ind = 'Y'
This query not only doesn't return the correct results, it also takes forever to run. My actual SQL is a lot longer and I've changed table names, etc but I hope that you can get the idea. If it matters, I will be creating a view based on this query.
Please advise on how to select multiple columns from the same table correctly and efficiently. Thanks!
I found put my extra stuff into CTE and add ROW_NUMBER to insure that I get only 1 row that I care about. it would look something like this. I only did for first 2 product info.
WITH PD_Info
AS ( SELECT Product_ID
,Product_Name
,Effective_Date
,ROW_NUMBER() OVER ( PARTITION BY Product_ID, Product_Name ORDER BY Effective_Date DESC ) AS RowNum
FROM Company.dbo.Product_Info)
SELECT A.*
,B.*
,PD_Info_1.Product_Name
,PD_Info_2.Product_Name
FROM Company.dbo.Company_Master AS A
LEFT JOIN Company.dbo.Compound_Info AS B
ON A.Claim_Number = B.Claim_Number
AND A.Customer_Number = B.Customer_Number
LEFT JOIN PD_Info AS PD_Info_1
ON B.Product_ID_1 = PD_Info_1.Product_ID
AND B.Fill_Date >= PD_Info_1.Effective_Date
AND PD_Info_2.RowNum = 1
LEFT JOIN PD_Info AS PD_Info_2
ON B.Product_ID_2 = PD_Info_2.Product_ID
AND B.Fill_Date >= PD_Info_2.Effective_Date
AND PD_Info_2.RowNum = 1

SQL: Want to alter the conditions on a join depending on values in table

I have a table called Member_Id which has a column in it called Member_ID_Type. The select statement below returns the value of another column, id_value from the same table. The join on the tables in the select statement is on the universal id column. There may be several entries in that table with this same universal id.
I want to adjust the select statement so that it will return the id_values for entries that have member_id_type equal to '7'. However if this is null then I want to return records that have member_id_type equal to '1'
So previously I had a condition on the join (commented out below) but that just returned records that had member_id_type equal to '7' and otherwise returned null.
I think I may have to use a case statement here but I'm not 100% sure how to use it in this scenario
SELECT TOP 1 cm.Contact_Relation_Gid,
mc.Universal_ID,
mi.ID_Value,
cm.First_Name,
cm.Last_Name,
cm.Middle_Name,
cm.Name_Suffix,
cm.Email_Address,
cm.Disability_Type_PKID,
cm.Race_Type_PKID,
cm.Citizenship_Type_PKID,
cm.Marital_Status_Type_PKID,
cm.Actual_SSN,
cm.Birth_Date,
cm.Gender,
mc.Person_Code,
mc.Relationship_Code,
mc.Member_Coverage_PKID,
sc.Subscriber_Coverage_PKID,
FROM Contact_Member cm (NOLOCK)
INNER JOIN Member_Coverage mc (NOLOCK)
ON cm.contact_relation_gid = mc.contact_relation_gid
AND mc.Record_Status = 'A'
INNER JOIN Subscriber_Coverage sc (NOLOCK)
ON mc.Subscriber_Coverage_PKID = sc.Subscriber_Coverage_PKID
AND mc.Record_Status = 'A'
LEFT outer JOIN Member_ID mi ON mi.Universal_ID = cm.Contact_Gid
--AND mi.Member_ID_Type_PKID='7'
WHERE cm.Contact_Relation_Gid = #Contact_Relation_Gid
AND cm.Record_Status = 'A'
Join them both, and use one if the other is not present:
select bt.name
, coalesce(eav1.value, eav2.value) as Value1OrValue2
from BaseTable bt
left join EavTable eav1
on eav1.id = bt.id
and eav1.type = 1
left join EavTable eav2
on eav2.id = bt.id
and eav2.type = 2
This query assumes that there is never more than one record with the same ID and Type.

Viewing records in a Row in a column from the same Table

I am crating a view to display records with contract dates in them.
The data for this view comes from two tables, one which stores the client details and another which stores the date info.
The dates themeselves are stored in the DateCol column and the ID for the DateCol column comes from TypeID eg 118 equals a Contract Start Date and 119 equals an End date.
This returns about 250 results.
The view I have built runs a lookup against the client id and shows the date from the date_type(ie 118 and 119 shows 01/01/2012 and 01/03/2012). If I add a third column that shows me 120, the total number of results is reduced to 6.
I need to see all the results but im not sure how to build a view that shows all of these. I cant modify the original database as it is a backed for Maximizer.
We are using SQL 2005 and I have built this using the Management STudio but my knowledge is a bit limited.
This is the code for my view:
SELECT *
FROM dbo.AMGR_Client_Tbl
INNER JOIN dbo.FOOTPRINTS_Companies_118
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_118.Client_Id
INNER JOIN dbo.FOOTPRINTS_Companies_119
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_119.Client_Id
INNER JOIN dbo.FOOTPRINTS_Companies_120
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_120.Client_Id
INNER JOIN dbo.FOOTPRINTS_Companies_121
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_121.Client_Id
WHERE ( dbo.AMGR_Client_Tbl.Record_Type = '1' ) AND ( dbo.AMGR_Client_Tbl.Name_Type = 'C' )
OR ( dbo.AMGR_Client_Tbl.Record_Type = '1' ) AND ( dbo.AMGR_Client_Tbl.Name_Type = 'C' )
Ok, First of all you should list the actual column names that you need on your view and not use *. I believe that you just need to change the INNER JOINs for LEFT JOINs. So it would be like this:
SELECT [List Your Columns Here]
FROM dbo.AMGR_Client_Tbl
LEFT JOIN dbo.FOOTPRINTS_Companies_118
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_118.Client_Id
LEFT JOIN dbo.FOOTPRINTS_Companies_119
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_119.Client_Id
LEFT JOIN dbo.FOOTPRINTS_Companies_120
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_120.Client_Id
LEFT JOIN dbo.FOOTPRINTS_Companies_121
ON dbo.AMGR_Client_Tbl.Client_Id =
dbo.FOOTPRINTS_Companies_121.Client_Id
WHERE ( dbo.AMGR_Client_Tbl.Record_Type = '1' ) AND ( dbo.AMGR_Client_Tbl.Name_Type = 'C' )
OR ( dbo.AMGR_Client_Tbl.Record_Type = '1' ) AND ( dbo.AMGR_Client_Tbl.Name_Type = 'C' )
Also, you should note that on your WHERE there seems to be a duplicated condition.

selecting latest rows per distinct foreign key value

excuse the title, i couldn't come up with something short and to the point...
I've got a table 'updates' with the three columns, text, typeid, created - text is a text field, typeid is a foreign key from a 'type' table and created is a timestamp. A user is entering an update and select the 'type' it corresponds too.
There's a corresponding 'type' table with columns 'id' and 'name'.
I'm trying to end up with a result set with as many rows as is in the 'type' table and the latest value from updates.text for the particular row in types. So if i've got 3 types, 3 rows would be returned, one row for each type and the most recent updates.text value for the type in question.
Any ideas?
thanks,
John.
select u.text, u.typeid, u.created, t.name
from (
select typeid, max(created) as MaxCreated
from updates
group by typeid
) mu
inner join updates u on mu.typeid = u.typeid and mu.MaxCreated = u.Created
left outer join type t on u.typeid = t.typeid
What are the actual columns you want returned?
SELECT t.*,
y.*
FROM TYPE t
JOIN (SELECT u.typeid,
MAX(u.created) 'max_created'
FROM UPDATES u
GROUP BY u.typeid) x ON x.typeid = t.id
JOIN UPDATES y ON y.typeid = x.typeid
AND y.created = x.max_created
SELECT
TYP.id,
TYP.name,
TXT.comment
FROM
dbo.Types TYP
INNER JOIN dbo.Type_Comments TXT ON
TXT.type_id = TYP.id
WHERE
NOT EXISTS
(
SELECT
*
FROM
dbo.Type_Comments TXT2
WHERE
TXT2.type_id = TYP.id AND
TXT2.created > TXT.created
)
Or:
SELECT
TYP.id,
TYP.name,
TXT.comment
FROM
dbo.Types TYP
INNER JOIN dbo.Type_Comments TXT ON
TXT.type_id = TYP.id
LEFT OUTER JOIN dbo.Type_Comments TXT2 ON
TXT2.type_id = TYP.id AND
TXT2.created > TXT.created
WHERE
TXT2.type_id IS NULL
In either case, if the created date can be identical between two rows with the same type_id then you would need to account for that.
I've also assumed at least one comment per type exists. If that's not the case then you would need to make a minor adjustment for that as well.