Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Believe I am overthinking this. So created a SQL report to generate data that looks like this:
Client# Parent# Industry Client Name A B C D E F G
1 0 Agriculture ABC Co. 0 0 0 50 0 0 0
2 1 Agriculture DEF Co. 25 0 0 0 0 0 0
3 2 Agriculture GHI Co. 0 0 0 0 0 0 75
There are like 10,000 rows. If you noticed, there is a client number and a parent number. The 3 results displayed above are sub companies that are all under the "ABC Co." business. What is the best way to group them all together into one line within an Excel report? Have the result look like this:
Client# Parent# Industry Client Name A B C D E F G Total
1 0 Agriculture ABC Co. 25 0 0 50 0 0 75 150
Was thinking possibilities being:
1) Customize SQL code to format the data to look the way I want it (would be nice bc every time I run the report, I would have to do minimal work after it collects the data). I understand though it is more appropriate to use SQL just to retreive the data.
2) There being an option within Excel to accomplish this.
3) Create a macro to sort through the data and format it the way I want.
Thank you for reading!
" So created a SQL report to generate data that looks like this:"
The reason for your downvotes is likely due to you not posting the SQL code here. Leaves me guessing at your table formats, so for my ease... select * from mytable is what I'll guess you've used. I'm left guessing column names too...in future questions, more information is helpful so I assume less.
select t1.client, t2.client, t3.client, t4.client, t1.parent, t2.parent, t3.parent, t1.*
from maytable t1
left join mytable t2 on t1.parent = t2.client
left join mytable t3 on t2.parent = t3.client
left join mytable t4 on t3.parent = t4.client
etc pending how deep this relation goes.
This will give you a list showing the parents. The t1.* is simply to grab the data columns related, you should write out your columns in full, I'm being lazy since no column list was supplied. The client IDs should look like this in your example (I've ignored parentID in my list below)
row 1 - 1 , 0, null , null
row 2 - 2 , 1 , 0, null
row 3 - 3 , 2 , 1, 0
Now we need a case statement...when the parent = 0 then show that client id.
select client_id, case when t1.parentid = 0 then t1.client_id
when t2.parentid = 0 then t2.client_id
when t3.parentid = 0 then t3.client_id
when t4.parentid = 0 then t4.clientID
end as parent_ID
, t1.*
from (same as above query)
You can take what was just written above and call it a sub query and select from it, this time grabbing the sums of the columns you want.
select parent_id, sum(a), sum(b), etc...
from
(select client_id, case when t1.parentid = 0 then t1.client_id
when t2.parentid = 0 then t2.client_id
when t3.parentid = 0 then t3.client_id
when t4.parentid = 0 then t4.clientID
end as parent_ID
, t1.*
from maytable t1
left join mytable t2 on t1.parent = t2.client
left join mytable t3 on t2.parent = t3.client
left join mytable t4 on t3.parent = t4.client
etc pending how deep this relation goes. ) a
group by parent_id
Unfortunately this is the best code I can provide with the limited info you've given.
Related
Table 1
Staff category hours cost
1 Cleaning 5 20
1 Scrubbing 6 30
1 Cleaning 8 40
2 Scrubbing 4 30
table 2
`
Staff type vendor category
1 part A Cleaning
1 full b Cleaning
1 full c Scrubbing
...’
To join these two tables I added a new col “type”:
Case when table1.hours=8
Then ”full”
Else ”part”
End as “type”
From table1
Left join table2 on type=table2.type
And Table 1.staff =table2.staff
And Table1.category=table 2.category
My desired outcome is
Staff category Cost vendor type
1 Cleaning 20 A. Part
1 Cleaning 40 B. Full
1 Scrubbing 30 C. Part
However the type=table2.type condition didn’t work so it became
Staff category Cost vendor type
1 Cleaning 20 A. Part
1 Cleaning 20 B. part
1 cleaning 40. A Full
1. Cleaning 40 B. Full
Below is for BigQuery Standard SQL
#standardSQL
SELECT staff, category, cost, vendor, type
FROM (
SELECT *, IF(hours = 8, 'full', 'part') AS type
FROM `project.dataset.table1`
) t1
LEFT JOIN `project.dataset.table2` t2
USING (type, staff, category)
If I have not understood, you want an implementation that creates a column in table1 and then joins with table2 on the condition table1.category = table2.category and table1.type = table2.type. If that's the case you could try with the following:
SELECT t1.Staff, t1.category, t1.cost, table2.vendor, t1.type
FROM (
SELECT *, CASE WHEN table1.hours = 8 THEN "full" ELSE "part" END as type
FROM table1
) t1
INNER JOIN table2
ON t1.category = table2.category
AND t1.type = table2.type
AND t1.staff = table2.staff
Table 1 looks like the following.
ID SIZE TYPE SERIAL
1 4 W-meter1 123456
2 5 W-meter2 123456
3 4 W-meter 585858
4 4 W-Meter 398574
As you can see. Items 1 and 2 both have the same Serial Number. I have an innerjoin update statement that will update the UniqueID on these devices based on linking their serial number to the list.
What I would like to do. Is modify by hand the items with duplicate serial numbers and scripted update the ones that are unique. Im presuming I have to reference the distinct command here somewhere buy not sure.
This is my update statement as is. Pretty simple and straight forward.
update UM00400
Set um00400.umEquipmentID = tb2.MIUNo
from UM00400 tb1
inner join AA_Meters tb2 on
tb1.umSerialNumber = tb2.Old_Serial_Num
where tb1.umSerialNumber <> tb2.New_Serial_Num
;WITH CTE
AS
(
SELECT * , rn = ROW_NUMBER() OVER (PARTITION BY SERIAL ORDER BY SERIAL)
FROM UM00400
)
UPDATE CTE
SET CTE.umEquipmentID = tb2.MIUNo
inner join AA_Meters tb2
on CTE.umSerialNumber = tb2.Old_Serial_Num
where tb1.umSerialNumber <> tb2.New_Serial_Num
AND CTE.rn = 1
This will update the 1st record of multiple records with the same SERIAL.
If i understand your question correctly below query will help you out :
;WITH CTE AS
(
// getting those serial numbers which are not duplicated
SELECT umSerialNumber,COUNT(umSerialNumber) as CountOfSerialNumber
FROM UM00400
GROUP BY umSerialNumber
HAVING COUNT(umSerialNumber) = 1
)
UPDATE A SET A.umEquipmentID = C.MIUNo
FROM UM00400 A
INNER JOIN CTE B ON A.umSerialNumber = B.umSerialNumber
INNER JOIN AA_Meters C ON A.umSerialNumber = C.Old_Serial_Num
I have a 2 tables:
Questions table with Question ID
Part Table:
Question ID
Part ID
BAllPartsRequired
The user will select some parts (or may select none) and depending on what was selected certain questions will be displayed.
I want to join the 2 tables for 3 scenerios but do them all in 1 query. I can write each scenerio individually (EDIT I thought I could but scenario 3 I can not get to work where it requires all found in part table to be selected) but can not figure out how to get them all in 1 query (I have done something similar before but cant remember how).
If no parts exist in part table for that question retruen the question
If any part selected exists in part table return question (i.e. user selects 1 part and 5 parts are associated to that question then the question will match and be returned). BAllPartsRequired = false
If user selects parts and ALL of the parts are associated to the question the question is returend but if NOT all parts are selected by user the question is not returend (i.e. user selects 3 parts and there are 4 parts in table then the user will not see the question, but if the user selectes all 4 parts the question will be shown). BAllPartsRequired = true
I am an advanced SQL programmer but this is eluding me and I know I have done this before but how do I get it to work in 1 query, do I do a nested join, a left join, a case on the where statement or something else.
Sample Data:
Question Form Association:
NFormAssociationID NQuestionID FormType
1 1 PAEdit
2 2 PAEdit
3 3 PAEdit
4 4 PAEdit
Question Part Form Association Table:
ID NFormAssociationID PartNumber BAllPartsRequired
1 1 1 0
2 2 2 1
3 2 3 1
Query without the new parts table added:
Select ROW_NUMBER() OVER(ORDER BY QL.NOrderBy) AS RowNumber,
QL.NQuestionID, QL.FieldName, QL.Question, QL.BRequired, QFL.FormFieldType, QFL.SingleMultipleSM,
QFL.CSSStyle
FROM dbo.QuestionFormAssociation QA WITH (NOLOCK)
INNER JOIN dbo.QuestionLookup QL WITH (NOLOCK) ON QA.NQuestionID = QL.NQuestionID
INNER JOIN dbo.QuestionFieldTypeLookup QFL WITH (NOLOCK) ON QL.NFieldTypeID = QFL.NFieldTypeID
WHERE QA.BActive = 1 AND QL.BActive = 1 AND QFL.BActive=1
AND QA.FormType = 'PAEdit'
ORDER BY QL.NOrderBy
Simple query using new table
Select ID
FROM dbo.QuestionPartFormAssociation
WHERE BAllPartsRequired = 1
AND PartNumber IN ('1', '2') --'1', '2', '3')
It sounds like you are trying to find the eligible questions, based on some criteria.
In this sitatuion, it is best to summarize first at the question level, and then apply logic to those summaries. Here is an example:
select q.questionid
from (select q.questionid,
max(case when qp.questionid is null then 1 else 0 end) as HasNoParts,
sum(case when qp.partid in (<user parts>) then 1 else 0 end) as NumUserParts,
count(qp.questionid) as NumParts,
max(qp.AllPartsRequired) as AreAllPartsRequired
from question q left outer join
questionpart qp
on q.questionid = qp.questionid
group by q.questionid
) q
where HasNoParts = 1 or -- condition 1
AreAllPartsRequired = 0 and NumUserParts > 0 or -- condition 2
AreAllPartsRequired = 1 and NmUserParts = NumParts -- condition 3
I've simplified the table and column names to make the logic clearer.
updated with full answer from OP:
Select ROW_NUMBER() OVER(ORDER BY QL.NOrderBy) AS RowNumber,
QL.NQuestionID, QL.FieldName, QL.Question, QL.BRequired, QFL.FormFieldType, QFL.SingleMultipleSM,
QFL.CSSStyle
FROM dbo.QuestionFormAssociation QA WITH (NOLOCK)
INNER JOIN dbo.QuestionLookup QL WITH (NOLOCK) ON QA.NQuestionID = QL.NQuestionID
INNER JOIN dbo.QuestionFieldTypeLookup QFL WITH (NOLOCK) ON QL.NFieldTypeID = QFL.NFieldTypeID
INNER JOIN (
select q.NFormAssociationID,
max(case when qp.NFormAssociationID is null then 1 else 0 end) as HasNoParts,
sum(case when qp.PartNumber in ('1','2','3') then 1 else 0 end) as NumUserParts,
count(qp.NFormAssociationID) as NumParts,
qp.BAllPartsRequired
from QuestionFormAssociation q
left outer join QuestionPartFormAssociation qp on q.NFormAssociationID = qp.NFormAssociationID
AND QP.BActive = 1
WHERE Q.FormType = 'PAEdit'
AND Q.BActive = 1
group by q.NFormAssociationID, qp.BAllPartsRequired
) QSUB ON QA.NFormAssociationID = QSUB.NFormAssociationID
WHERE QA.BActive = 1 AND QL.BActive = 1 AND QFL.BActive=1
AND (
QSUB.HasNoParts = 1 -- condition 1
OR (QSUB.BAllPartsRequired = 0 and QSUB.NumUserParts > 0) -- condition 2
OR (QSUB.BAllPartsRequired = 1 and QSUB.NumUserParts = QSUB.NumParts) -- condition 3
)
ORDER BY QL.NOrderBy
I have three tables as described below:
dbo.ServiceEntry
ID RunLogEntry Reconciled
1 0 1
2 4 1
3 5 1
dbo.ServiceEntryPart
ID ServiceEntryID PartId ServiceEntryTypeID
1 1 3 1
2 2 4 2
3 2 4 1,2
dbo.Part
ID Desc Active (bitfield)
3 xyz 1
4 abc 1
Query as follows:
SELECT *
FROM ServiceEntry AS S
WHERE (S.RunLogEntryID is not null) AND (S.Reconciled=#ReconciledValue)
AND EXISTS (SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part on SEP.PartID = Part.ID
WHERE ((#ActivePart = 0 AND Part.Active is not null)
OR (#ActivePart = 1 and Part.Active = 0))
AND (#ServiceTypes is null
OR CHARINDEX(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+#ServiceTypes+',') > 0))
OR (NOT EXISTS (SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part on SEP.PartID = Part.ID))
service entry has some records which contain runlogentry id of 0. If the runlogentryid value in service entry table is 0 then there will be no service entry part record for that service entry. Thats why I split them into two as you would notice from the query for example exists and not exists. the exists statement takes care of all service entries which have service entry parts and for these the filters will be applicable. If the filters have values then the not exist block will be not be needed because filters servicetypeids and activepart are for only records which have service entry parts.
So in other words if no params are passed the first exists block fetches service entries which have service parts and the not exists fetches service entries which have runlogentry id of 0 OR NOT null. This works great as it is. The problem is when the params are passed I would need to exclude the serviceentries which do not have service entry parts and when they are present I do not get the rigth results. I hope I did an okay job explaining the problem..Please help
Without trying to understand the rest of your SQL, if all you want to do is avoid the NOT EXISTS clause when your parameters are null you can do something like this.
SELECT *
FROM ServiceEntry AS S
JOIN
WHERE (S.RunLogEntryID is not null) AND (S.Reconciled=#ReconciledValue)
AND EXISTS (SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part on SEP.PartID = Part.ID
WHERE ((#ActivePart = 0 AND Part.Active is not null)
OR (#ActivePart = 1 and Part.Active = 0))
AND (#ServiceTypes is null
OR CHARINDEX(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+#ServiceTypes+',') > 0))
OR (#ReconciledValue is null and #ActivePart is null and #ServiceTypes is null
and (NOT EXISTS (SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part on SEP.PartID = Part.ID)))
This probably isn't exactly what you want, to be honest the query seems all over the place.
You're probably looking for an active part filter like '(#ActivePart is null or #ActivePart = Part.Active)'. Your exists is implicitly taken care of by an inner join. A query that I believe is close to what you're looking for is below.
select *
FROM ServiceEntry AS S
INNER JOIN ServiceEntryPart AS SEP ON SEP.ServiceEntryID = S.ServiceEntryID
INNER JOIN Part AS P ON P.PartID = SEP.PartID
WHERE S.RunLogEntryID is not null
and S.Reconciled = #ReconciledValue
and (#ActivePart is null or #ActivePart = Part.Active)
and (#ServiceTypes is null or charindex(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+#ServiceTypes+',') > 0
I can't be sure because I don't have the business definitions of your columns, but I suspect your conditions dealing with Part.Active are wrong. I would expect the values to be 0 or 1, not NULL or 0. So I should think the test should return TRUE when the parameter is NULL or the parameter matches the column.
Your CHARINDEX function has the parameters reversed.
You need additional parentheses to get the correct order of operation and your OR NOT EXISTS clause needs additional conditions to make it only true if the parameters are NULL.
I believe the following is much closer to what you are looking for. But I am worried about the ServiceTypes test. It will only work reliably if the parameter contains a single ServiceTypeID. If it contains multiple IDs it may not work. For example, I would think a parameter value of '1,3' should match a list of '1,2,3', but it won't.
SELECT *
FROM ServiceEntry AS S
WHERE (S.RunLogEntryID IS NOT NULL)
AND (S.Reconciled=#ReconciledValue)
AND( EXISTS(
SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part ON SEP.PartID = Part.ID
WHERE( #ActivePart IS NULL
OR #ActivePart = Part.Active
)
AND ( #ServiceTypes IS NULL
OR CHARINDEX( ','+#ServiceTypes+',',
','+cast(SEP.ServiceTypeIDs as varchar(255))+','
) > 0
)
)
OR( #ActivePart IS NULL
AND #ServiceTypes IS NULL
AND NOT EXISTS( SELECT ServiceEntryID
FROM ServiceEntryPart SEP
JOIN Part on SEP.PartID = Part.ID
)
)
)
I have a table that saves the possible states of other tables (entities).
But now I need to find equivalence of states between two entities.
The table structure is something like this
ID TableID StateValue StateDefinition StateDescription
================================================================
1 1 1 Created Just created
2 1 2 Dropped Just Dropped
3 2 1 Created Just Created
4 2 2 Aproved Passed the revision
5 2 3 Dropped Just dropped
I want to get equivalent (comparing text of state) which as a result get this:
TableID1 StateValue1 TableID2 StateValue2 StateDefinition
=============================================================================
1 1 2 1 Created
1 2 2 3 Dropped
My question is, how can it be done??
Do a self join on the table.
A general case might look like:
SELECT A.TableID as TableId1,
A.StateValue as StateValue1,
B.TableId as TableId2,
B.StateValue as StateValue2,
A.StateDefinition
FROM
Table A
INNER JOIN Table B
ON (A.TableId <> B.TableId and A.StateDefiniton = B.StateDefinition)
select t1.TableID as TableID1,
t1.StateValue as StateValue1,
t2.TableID as TableID2,
t2.StateValue as StateValue2,
t1.StateDefinition
from MyTable t1
inner join MyTable t2 on t1.TableID = 1 and t2.TableID = 2
where t1.StateValue = t2.StateValue
and t1.StateDefinition = t2.StateDefinition