Updating table by using multiple joins on the same table - sql-server

In the picture that is attached, I highlighted two columns. The left column is a the StartTime and the right column is an ID. I need the IDs that are NULL to be 164, since all 4 of those rows have the same exact StartTime. Is there a way to code one update statement to gather the NULL rows and rows with a value, and then update the NULL rows with a value that has the same StartTime? Any code would be very helpful.
Picture: Query Results

UPDATE t
SET t.ID = x.ID
FROM YourTable t
INNER JOIN (SELECT DISTINCT ID, StartTime
FROM YourTable
WHERE ID IS NOT NULL
) x
ON x.StartTime = t.StartTime
WHERE t.ID IS NULL
This is how I would do it.

Related

Issue with query in DB2

I was using below query in sql server to update the table "TABLE" using the same table "TABLE". In sql server the below query is working fine.But in DB2 its getting failed.Not sure whether I need to make any change in this query to work in DB2.
The error I am getting in DB2 is
ExampleExceptionFormatter: exception message was: DB2 SQL Error:
SQLCODE=-204, SQLSTATE=42704
This is my input Data and there you can see ENO 679 is repeating in both round 3 and round 4.
My expected output is given below. Here I am taking the ID and round value from round 4 and updating rownumber 3 with the ID value from rownumber 4.
My requirement is to find the ENO which is exist in both round 3 and round 4 and update the values accordingly.
UPDATE TGT
SET TGT.ROUND = SRC.ROUND,
TGT.ID = SRC.ID
FROM TABLE TGT INNER JOIN TABLE SRC
ON TGT.ROUND='3' and SRC.ROUND='4' and TGT.ENO = SRC.ENO
Could someone help here please. I tried something like this.But its not working
UPDATE TABLE
SET ID = (SELECT t.ID
FROM TABLE t, TABLE t2
WHERE t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3'
) ,
ROUND= (SELECT t.ROUND
FROM TABLE t, TABLE t2
WHERE t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3')
where ROUND='3'
You may try this. I think the issue is you are not relating your inner subquery with outer main table
UPDATE TABLE TB
SET TB.ID = (SELECT t.ID
FROM TABLE t, TABLE t2
WHERE TB.ENO=t.ENO ---- added this
and t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3'
) ,
TB.ROUND= (SELECT t.ROUND
FROM TABLE t, TABLE t2
WHERE TB.ENO=t.ENO --- added this
and t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3')
where tb.ROUND='3'
Try this:
UPDATE MY_SAMPLE TGT
SET (ID, ROUND) = (SELECT ID, ROUND FROM MY_SAMPLE WHERE ENO = TGT.ENO AND ROUND = 4)
WHERE ROUND = 4 AND EXISTS (SELECT 1 FROM MY_SAMPLE WHERE ENO = TGT.ENO AND ROUND = 4);
The difference with yours is that the correlated subquery has to be a row-subselect, it has to guarantee zero or one row (and will assign nulls in case of returning zero rows). The EXISTS subquery excludes rows for which the correlated subquery will not return rows.

How to get data from other table within a group by query?

I have tried to group records from one table which have similar SerialNo. And I also want to show a column records from other table that has relation ship with table one using SerialNo.
I have a table 1:
And table 2:
My Query is:
select CIT_SERIALNUMBER, COUNT(CIT_ID)
as Cases from Table_2 where CIT_SOURCEID like '%E_One%'
and (CIT_CREATED BETWEEN '2018-01-15'AND '2019-06-15') and CIT_SERIALNUMBER is not null
group by CIT_SERIALNUMBER
having COUNT(CIT_ID)>1 order by min(CIT_CREATED) desc
Here is the result table:
In the query above I’ve got only CIT_SERIALNUMBER records from Table_2. But I also want to get the data from Table_1 column ComputerName. So, the expected result is:
Note: The two table 1 and 2 can be join by Column T1_Serial and CIT_SERIALNUMBER.
Please help me to re-write the sql query to achieve the expected result above.
If I understood your column names correctly, try this:
select CIT_SERIALNUMBER, ComputerName, COUNT(CIT_ID)
as Cases from Table_2 join Table_1 on Table_2.CIT_SERIALNUMBER=Table_1.Serial where CIT_SOURCEID like '%E_One%'
and (CIT_CREATED BETWEEN '2018-01-15'AND '2019-06-15') and CIT_SERIALNUMBER is not null
group by CIT_SERIALNUMBER
having COUNT(CIT_ID)>1 order by min(CIT_CREATED) desc
Try this-
SELECT A.ComputerName,
CIT_SERIALNUMBER,
COUNT(CIT_ID) AS Cases
FROM table_1 A
INNER JOIN Table_2 B ON A.Column T1_Serial = CIT_SERIALNUMBER.
WHERE B.CIT_SOURCEID LIKE '%E_One%'
AND (B.CIT_CREATED BETWEEN '2018-01-15' AND '2019-06-15')
AND B.CIT_SERIALNUMBER IS NOT NULL
GROUP BY A.ComputerName,B.CIT_SERIALNUMBER
HAVING COUNT(B.CIT_ID) > 1
ORDER BY MIN(B.CIT_CREATED) DESC;
It look odd, but I've got a solution for this:
I select all duplicated records from Table_2 first
Then I join Table_1 with result set of Table_2 to view column from both tables
Then I use another select to select data from result set above and group by all records.
Here is the query:
select z.CIT_SERIALNUMBER, z.ComputerName, z.Cases from (
SELECT y.CIT_SERIALNUMBER, x.ComputerName, y.Cases
FROM Table_1 x
right JOIN (
select CIT_SERIALNUMBER, COUNT(CIT_ID)
as Cases from Table_2 where CIT_SOURCEID like '%E_One%'
and (CIT_CREATED BETWEEN '2018-01-15'AND '2019-06-15') and CIT_SERIALNUMBER is not null
group by CIT_SERIALNUMBER
having COUNT(CIT_ID)>1
) y ON y.CIT_SERIALNUMBER = x.SerialNo) z group by CIT_SERIALNUMBER, z.ComputerName, z.Cases
Result set:

How can I find all rows in master table with the same records in its child table?

I need to find every record in TableA that has the same child records in TableB
for example :
tableA
keyA
1
2
3
tableB
keyA....keyB....valueB
1...........11...........4
1...........12...........5
2...........21...........4
2...........22...........5
3...........31...........4
3...........32...........6
So suppose I want to search for doubles.
It should return the two first rows in tableA because both these rows have the same amount of child records in tableB with the same values for valueB
the first row in tableA as 2 child records, one with valueB = 4 and one with valueB = 5
the second row in tableA also has 2 child records, and with the same values in field tableB
the third row also has 2 child records, but with different values in field valueB
so the 2 first rows in tableA should be returned if I search for doubles.
I tried this but it gives an error on the first subquery, it may not return more than one value :
select *
from tableA t1
where (select t2.valueB
from tableB t2
where t2.keyA = 1
)
in
(select t3.valueB
from tableB t3
where t3.keyA = t1.KeyA
)
So, can this be done ?
EDIT : the output for my example should be
tableA
keyA
1
2
Edit 2 : rephrasing the question :
1. tableB is a childtable for tableA
2. there will be records in tableA that have records in tableB with the same values for field valueB as other records in tableA
3. I want to find these records.
EDIT: findings so far :
this query seems to produce what I need :
declare #keyA int = 1
select distinct r.keyA
from tableA r
inner join tableB eb on r.keyA = eb.keyA
where (select count(1) from tableB eb1 where eb1.keyA = #keyA) = (select count(1) from tableB eb2 where eb2.keyA = r.keyA)
and eb.valueB in (select eb4.valueB from tableB eb4 where eb4.keyA = #keyA)
The first where clause only allows master records where the number of child records are the same as for the first row in tableA. (all rows in tableA are found)
The second where clause only allows master records where the valueB of the child records are also present in the child records for the first row in tableA. (only first 2 rows in tableA are found)
The idea is to get all master records (tableA) that have the same amount of child records as the first row, and where all the values for valueB in these child records are also present in the child records for the first row of tableA.
Both where clauses combined should give me what I need, that is what I am hoping.
It seems to produce the correct result, but I would like some confirmation if its correct or wrong.
select
t1.A
from
t1
where exists(
select 1 from t2 where t2.keya=t1.keya
group by t2.keya,t2.valueb
having count(*)>1
)

Ignore condition in WHERE clause when column is NULL

I do have table were one row (with Type =E) is related to another row.
I have written query to return COUNT of those related rows. The problem is that there is no explicit relationship (like ID column that would clearly say which row is related to other row). Therefore I am trying to find relationship based on multiple conditions in WHERE clause.
The problem is that in few cases, the columns A and B could be NULL (for records where TYPE = 'M'). In such a cases I would like to ignore that condition, so It would use only first 3 conditions to determine relationship.
I have tried CASE Statement but is not working as expected:
SELECT [T1].[ID],[T1].[AlphaId],[T1].[Type],[T1].[A],[T1].[B],[T1].[Date],[T1].[ServiceID]
,( SELECT COUNT(*)
FROM MyTable T2
WHERE [T1].[AlphaId]=[T2].[AlphaId] AND
[T1].[Date]=[T2].[Date] AND
[T1].[ServiceID]=[T2].[ServiceID] AND
[T2].[A]=CASE WHEN [T2].[A] IS NULL THEN NULL ELSE [T1].[A] END AND
[T2].[B]=CASE WHEN [T2].[B] IS NULL THEN NULL ELSE [T1].[B] END AND
[T2].[Type]='M'
) as TotalCount
FROM MyTable T1
WHERE [T1].[Type] = 'E'
I can't ignore that condition, as for some cases the Date, ServiceID could be same, however it's the A, B which differs them. Luckily where A, B IS NULL, it is the Date, ServiceID which differs those two records.
http://sqlfiddle.com/#!3/c98db/1
Many thanks in advance.
You could join the tables and use COUNT and GROUP BY to get the counts. Then you can JOIN [A] and [B] if they are equal or NULL.
SELECT [T1].[ID],[T1].[AlphaId],[T1].[Type],[T1].[A],[T1].[B],[T1].[Date],[T1].[ServiceID], count([T2].[ID])
FROM MyTable T1
INNER JOIN MyTable T2 ON [T1].[AlphaId]=[T2].[AlphaId] AND
[T1].[Date]=[T2].[Date] AND
[T1].[ServiceID]=[T2].[ServiceID] AND
([T2].[A]= [T1].[A] OR [T2].[A] IS NULL )AND
([T2].[B]= [T1].[B] OR [T2].[B] IS NULL )AND
[T2].[Type] <> [T1].[Type]
WHERE [T1].[Type] = 'E'
GROUP BY [T1].[ID],[T1].[AlphaId],[T1].[Type],[T1].[A],[T1].[B],[T1].[Date],[T1].[ServiceID]

SQL Server Comparing Subsequent Rows for Duplicates

I am trying to write a SQL Server query but have had no luck and was wondering if anyone may have any ideas on how to achieve my query.
What i'm trying to do:
I have a table with several columns naming the ones that i am dealing with TaskID, StatusCode, Timestamp. Now this table just holds tasks for one of our systems that run throughout the day and when something runs it gets a timestamp and the statuscode depending on the status for that task.
Sometimes what happens is the task table will be updated with a new timestamp but the statusCode will not have changed since the last update of the task so for two or more consecutive rows of a given task the statusCode can be the same. When i say consecutive rows i mean with regards to timestamp.
So example task 88 could have twenty rows at statusCode 2 after which the status code changes to something else.
Now what i am trying to do with no luck at the moment is to retrieve a list from this table of all the tasks and the statuscodes and the timestamps but in the case where i have more than one consecutive row for a task with the same statuscode i just want to take the first row with the lowest timestamp and ignore the rest of the row until the statuscode for that task changes.
To make it simpler in this case you can assume that i have a taskid which i am filtering on so i am just looking at a single task.
Does anyone have any ideas as to how i can do this or perhaps something that i coudl probably read to help me?
Thanks
Irfan.
This are a couple ways of getting what you want:
SELECT
T1.task_id,
T1.status_code,
T1.status_timestamp
FROM
My_Table T1
LEFT OUTER JOIN My_Table T2 ON
T2.task_id = T1.task_id AND
T2.status_timestamp < T1.status_timestamp
LEFT OUTER JOIN My_Table T3 ON
T3.task_id = T1.task_id AND
T3.status_timestamp < T1.status_timestamp AND
T3.status_timestamp > T2.status_timestamp
WHERE
T3.task_id IS NULL AND
(T2.status_code IS NULL OR T2.status_code <> T1.status_code)
ORDER BY
T1.status_timestamp
or
SELECT
T1.task_id,
T1.status_code,
T1.status_timestamp
FROM
My_Table T1
LEFT OUTER JOIN My_Table T2 ON
T2.task_id = T1.task_id AND
T2.status_timestamp = (
SELECT
MAX(status_timestamp)
FROM
My_Table T3
WHERE
T3.task_id = T1.task_id AND
T3.status_timestamp < T1.status_timestamp)
WHERE
(T2.status_code IS NULL OR T2.status_code <> T1.status_code)
ORDER BY
T1.status_timestamp
Both methods rely on there being no exact matches of the status_timestamp values (two rows can't have the same exact status_timestamp for a given task_id.)
Something like
select TaskID,StatusCode,Min(TimeStamp)
from table
group by TaskID,StatusCode
order by 1,2
Note that is statuscode can duplicate, you will need an additional field, but hopefully this can point you in the right direction...
Something like the following should get you in the right direction....
CREATE TABLE #T
(
TaskId INT
,StatusCode INT
,StatusTimeStamp DATETIME
)
INSERT INTO #T
SELECT 1, 1, '2009-12-01 14:20'
UNION SELECT 1, 2, '2009-12-01 16:20'
UNION SELECT 1, 2, '2009-12-02 09:15'
UNION SELECT 1, 2, '2009-12-02 12:15'
UNION SELECT 1, 3, '2009-12-02 18:15'
;WITH CTE AS
(
SELECT TaskId
,StatusCode
,StatusTimeStamp
,ROW_NUMBER() OVER (PARTITION BY TaskId, StatusCode ORDER BY TaskId, StatusTimeStamp DESC) AS RNUM
FROM #T
)
SELECT TaskId
,StatusCode
,StatusTimeStamp
FROM CTE
WHERE RNUM = 1
DROP TABLE #T

Resources