How to join a column to another column based on two conditions - sql

I am at a bit of a loss why this is not working/updating. I have a 'sites' table and a 'visit' table. The 'sites' table contains all the unique 'sites' with in the DB and the 'visit' table contains all the unique visits to all the sites.
Site
site_id
region
site
1
a
a
2
a
b
3
b
a
4
b
b
Visit
visit_id
region
site
date
site_id
1
a
a
1
2
a
b
2
3
b
a
3
4
b
b
2
5
c
a
3
6
c
b
1
7
d
a
2
8
d
b
2
When region and site equal each other I want the site_id to populate in the 'visit' table. Here is what I have tried. It does not throw and error but nothing populates in the visit.site_id.
update visit a
set site_id =
(select s.site_id
from site s
where (s.region, s.site) = (a.region, a.site));

Your way has a problem and if even it works, it does not work correctly because if there are the same tuples in both tables your query will update all of them.
update visit a
set site_id =
(select s.site_id
from sites s
where (s.region, s.site) = (a.region, a.site) and a.region = a.site);
rewriting in another way:
update visit a
set site_id =
(select s.site_id
from sites s
where s.region = a.region and s.site = a.site and a.region = a.site);
Here's the result(my PostgreSQL version is 13):

Related

SQL Server update and replace values with values from another table

I have two tables:
Connections:
id user_id connection_info
------------------------------
1 1 ...
2 1 ...
3 2 ...
Lists:
id connection_id name
-----------------------
1 1 ...
2 2 ...
3 1 ...
I currently have user_id's in the lists.connection_id column. I would like to join the lists table with the connections table by connections.user_id = lists.connection_id and then replace the lists.connection_id with the corresponding id from the connections table.
You could use UPDATE FROM like this:
update l
set l.connection_id = c.id
from connections c join lists l on c.user_id = l.connection_id
Initially you would want to test what you are going to update, running a SELECT statement:
select l.connection_id as con_old
, c.id as con_new
, ... (other cols you might want to check)
from connections c join lists l on c.user_id = l.connection_id

create a table out of another table

I want to create a table whose columns are populated using existing tables.The table I want is
tbl_selection
Name of guide No of trainees selected No of trainees alotted
A 2 1
B 1 1
C 1 1
The column Name of guide is populated using tbl_registration , No of trainees selected using tbl_pencil and No of trainees alotted using allot_guide
tbl_registration
Guide_Name PIN_NO Designation
A 1 SC-C
B 2 SC-D
C 3 SC-E
tbl_pencil
TL_NO Student_name College Guide_Name
TOO1 P PQR A
T002 Q XYZ A
T003 R RST B
T004 S UVW C
tbl_alotguide
TL_NO Student_name Guide_Name
T001 P A
TOO3 R B
TOO4 S C
Please help me find an appropriate query for the above
You can update the second and third columns using the UPDATE statement.
UPDATE tbl_selection
SET No_of_trainees_selected =
(SELECT count(*)
FROM tbl_pencil
WHERE tbl_selection.name_of_guide = tbl_pencil.guide_name
GROUP BY tbl_pencil.guide_name)
You can view UPDATE statement documentation in the next link:
https://www.techonthenet.com/oracle/update.php

SQL join to table with 3 possible cases: table can have no records, match 1 or more, records or require all records found to match

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

SQL query get record table A based on parentid Table B

[SOLVED: thanks to bluefeet and Brian I got to build this working query (turned out I also needed a fourth table / view)]"
SELECT A.SalesLineID, A.ArticleResultID, B.ID, C.ID, D.Value
FROM VIEWA AS A
INNER JOIN TABLEB AS B ON A.ArticleResultID = B.ArticleResultID
AND B.Name = N'Collect' AND DAPR.Value = 1
INNER JOIN TABLEC AS C ON B.ArticleResultID = C.ID
AND C.Name='Assemble'
AND C.Value = 1
INNER JOIN TABLED AS D ON D.ArticleResultID = C.ParentId
AND D.Name = 'IndexY'
WHERE (A.SalesID = #SalesID)
[UPDATE: I've made a mistake assuming IndexY/Color and ProdId where fields Table A is some kind of parameter / property table with only 5 columns ID - NAME - VALUE - ARTICLERESULTID - PRODID. IndexY is a value of the Name field..]
I'm having trouble building the right sql query to get this trick done:
I have the following 2 tables:
Table A
ID Name Value ArticleResultID ProdID Color
1 Operation Collect 110 10 BLACK
2 IndexY 10 110 10 -
3 Operation Collect 101 11 WHITE
Table B
ID ParentID Name Value
101 110 Assemble 1
101 100 Assemble 0
Steps:
Find record in A with Name = Operation and Value = Collect and ProdId = 11 AS ORG_A
Find record in B With B.ID = ORG_A.ArticleResultId AND B.NAME = 'Assemble'AND B.VALUE = 1 AS B
Find record in A With A.ArticleResultID = B.ParentID as NEW_A
In the above scenario thats ORG_A.ArticleResultID = 11 --> B.ParentID = 110 --> NEW_A.ARTICLERESULTID = 110 --> (IndexY - Value - 10)
Much appreciated if someone can tell me how to build this query..
Best regards,
Mike D
[OLD DESCRIPTION:]
I'm having trouble building the right sql query to get this trick done:
I have the following 2 tables:
Table A
Name Value ArticleResultID IndexY Color ProdID
Operation Collect 110 10 - 0
Operation Collect 101 _ Black 100
Table B
ID ParentID Name Value Dx Dy
101 110 Assemble 1 1000 500
101 100 Assemble 0 400 300
I want to fetch all records from A where NAME equals 'operation', VALUE equals 'Collect' and PRODID = '100' but I also want (here's my problem) the IndexY value of the record in Table A with the PARENTID in Table B which joins on TABLE B.ID = A.ArticleResultID AND Name = 'Assemble' and VALUE = '1'
In the above scenario thats ParentID 110 which gives me the record in Table A with ArticleResultID 110 with IndexY (10).
Much appreciated if someone can tell me how to build this query..
Best regards,
Mike D
Since your requirements are not the clearest. How about this:
SELECT a1.*, a2.indexy as additionalIndexY
FROM ta a1
INNER JOIN tb b
ON a1.articleresultid = b.id
INNER JOIN ta a2
ON b.parentid = a2.articleresultid
WHERE a1.name = 'Operation'
AND a1.prodid = 100
AND b.name = 'Assemble'
AND b.value = 1
Here is a sqlfiddle with a working version
If you just want the record with the 110 articleresultid, then:
SELECT a2.*
FROM ta a1
INNER JOIN tb b
ON a1.articleresultid = b.id
INNER JOIN join ta a2
ON b.parentid = a2.articleresultid
WHERE a1.name = 'Operation'
AND a1.prodid = 100
AND b.name = 'Assemble'
AND b.value = 1
see the sqlfiddle for the second example
Does this work for you?
SELECT a.*,c.IndexY
FROM [TableA] a
JOIN [TableB] b ON a.ArticleResultId = b.id
AND b.Name ='Assemble'
AND b.Value = 1
JOIN [TableA] c ON b.ParentId = c.ArticleResultID
WHERE a.name = 'Operation'
AND a.Value = 'Collect'
AND a.ProdId = 100

SQL select column equivalence

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