SQL execution time - sql

I face execution time problem here ,really upset
UPDATE [OT]
SET AAA = 8
WHERE ID in
(
select UID from [IP] B
inner join [OT] A
on B.ADDR = A.ADDR and A.ID=B.ID
)
AND AAA= 6 ;
OT table have duplicate ID, count(*) about 900000 rows
IP table have unique ID, count(*) about 800000 rows
AAA is a column of OT table type: tinyint
select count(*) from OT where AAA=6 about 150000
I do not know why this query will take more than 1 hour ??
My other similar query only take 10 seconds

I would just write this more simply as:
UPDATE OT
SET AAA = 8
FROM OT
WHERE EXISTS (SELECT 1 FROM IP WHERE IP.ADDR = OT.ADDR AND IP.ID = OT.ID) AND
OT.AAA = 6 ;
For performance, you want indexes on OT(AAA) and IP(ADDR, ID).

Related

How to update table from another table, with 2 columns

I am using SQL Server database and want a way to update MachinesSummary.ShareCount.
Here are my two tables
MachinesSummary
ID Machine1 Machine2 ShareCount
-------------------------------
1 A J NULL
2 K S NULL
3 A E NULL
4 J A NULL
5 Y U NULL
6 S W NULL
7 G A NULL
8 W S NULL
The other table is MachineDetails
ProcessNo Machine
------------------
1 A
1 H
1 W
2 A
2 J
2 W
3 Y
3 K
4 J
4 A
I want to update ShareCount in the MachineSummary table with the count of processes that both Machine1 and Machine2 share.
For record 1 in the MachineSummary table, I want the number of processes both share in MachineDetails which is 1 in this case
While for record 4 the ShareCount is 2
I tried this
UPDATE M
SET ShareCount = COUNT(DISTINCT X.ProcessNo)
FROM
(SELECT ProcessNo, ',' + STRING_AGG(Machine,',') + ',' Machines
FROM MachineDetails
GROUP BY ProcessNo) X
INNER JOIN MachinesSummary M ON X.Machines LIKE '%'+ M.Machine1 + '%'
AND X.Machines LIKE '%'+ M.Machine2 + '%'
But I wonder if there is an easier high performance way
The MachineDetails table has 250 million rows.
Well, I would use a self-join to get the number of combinations:
UPDATE M
SET ShareCount = num_processes
FROM MachinesSummary M JOIN
(SELECT md1.Machine as machine1, md2.Machine as machine2, COUNT(*) as num_processes
FROM MachineDetails md1 JOIN
MachinesDetails md2
ON md1.processno = md2.processno
GROUP BY md1.Machine, md2.Machine
) md
ON md.Machine1 = M.machine1 AND md.Machine2 = M.machine2;
I would use an updatable CTE here:
WITH cte AS (
SELECT Machine, COUNT(*) AS cnt
FROM MachineDetails
GROUP BY Machine
),
cte2 AS (
SELECT ShareCount, COALESCE(t1.cnt, 0) AS m1_cnt, COALESCE(t2.cnt, 0) AS m2_cnt
FROM MachineSummary ms
LEFT JOIN cte t1 ON t1.Machine1 = ms.Machine
LEFT JOIN cte t2 ON t2.Machine2 = ms.Machine
)
UPDATE cte2
SET ShareCount = m1_cnt + m2_cnt;
The logic of the first CTE involving the MachineDetails table is to get the counts for every machine. The second CTE joins this counts CTE to the MachineSummary table twice, once for each of machine 1 and 2. Then, we update this second CTE and assign the sum of counts.

Update a range of rows in a table where the condition is in another table

example:
table 1
invoice line article price
1 1 pen 10
1 2 mouse 11
1 3 paper 15
2 1 ... 25
2 2 ... 80
2 3 ...
2 4 ....
table 2
invoice date
1 2014-01-03 00:00:00.0000
2 2014-05-12 00:00:00.0000
3 2014-06-17 00:00:00.0000
how can I update the price only on the rows where the invoice date is for example the month of november
I know that i must use a join but i'm already joining this table for doing other stuff in the same query:
UPDATE invoicelines
SET invoicelines.netprice = ART.price
FROM invoicelines IL INNER JOIN items ITM
ON IL.item = ITM.item
i want to update the invoicelines with a specified date, but this date is in another table, and the situation is similar to the first example
update table1
set price = price + 10
from table1 t1 join table2 t2 on t1.invoice = t2.invoice
where month(t2.date) = 11
As to "I know that i must use a join": No, you don't have to join. When a condition is in another table you would usually use EXISTS or IN.
update table1
set price = ...
where invoice in
(
select invoice
from table2
where month(`date`) = 11
);
Or:
update table1
set price = ...
where exists
(
select *
from table2
where month(table2.`date`) = 11
and table2.invoice = table1.invoice
);
You forgot to name your dbms. Date functions are mostly dbms specific, so a MONTH function may be available or not.
I Solved With This
UPDATE Invoicelines
SET Invoicelines.NetPrice = ART.Price
FROM Invoicelines BR INNER JOIN Items ART join InvoiceHead bt on month(bt.docdate)=11
ON BR.Item = ART.Item
where BR.sheetNumber=bt.sheetNumber

SQL Update Skipping duplicates

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

Tricky SQLite query, could use some assistance

I have a rather confusing SQLite query that I can't seem to quite wrap my brain around.
I have the following four tables:
Table "S"
sID (string/guid) | sNum (integer)
-----------------------------------
aaa-aaa 1
bbb-bbb 2
ccc-ccc 3
ddd-ddd 4
eee-eee 5
fff-fff 6
ggg-ggg 7
Table "T"
tID (string/guid) | ... other stuff
-----------------------------------
000
www
xxx
yyy
zzz
Table "S2TMap"
sID | tID
-------------------
aaa-aaa 000
bbb-bbb 000
ccc-ccc xxx
ddd-ddd yyy
eee-eee www
fff-fff 000
ggg-ggg 000
Table "temp"
oldID (string/guid) | newID (string/guid)
------------------------------------------
dont care fff-fff
dont care ggg-ggg
dont care zzz
What I need is to be able to get the MAX() sNum that exists in a specified "t" if the sID doesn't exist in the temp.NewID table.
For example, given the T '000', '000' has S 'aaa-aaa', 'bbb-bbb', 'fff-fff', and 'ggg-ggg' mapped to it. However, both 'fff-fff' and 'ggg-ggg' exist in the TEMP table, which means I need to only look at 'aaa-aaa' and 'bbb-bbb'. Thus, the statement would return "2".
How would I go about doing this?
I was thinking something along the lines of the following for selecting s that don't exist in the "temp" table, but I'm not sure how to get the max of the seat and only do it based on a specific 't'
SELECT s.sID, s.sNum FROM s WHERE NOT EXISTS ( SELECT newID from temp where tmp.newID = s.sID)
Thanks!
Give this a try:
select max(s.sNum) result from s2tmap st
join s on st.sId = s.sId
where st.tId = '000' and not exists (
select * from temp
where temp.newId = st.sId)
Here is the fiddle to play with.
Another option, probably less efficient would be:
select max(s.sNum) result from s2tmap st
join s on st.sId = s.sId
where st.tId = '000' and st.sId not in (
select newId from temp)
The following query should give you a list of Ts and their max sNums (as long as all exist in S and S2TMap):
SELECT t.tID, MAX(sNum)
FROM S s
JOIN S2TMap map on s.sID=map.sID
JOIN T t on map.tId=t.tID
LEFT JOIN temp tmp on s.sID=tmp.newID
WHERE tmp.newID IS NULL
You were close, you just had to join on S2TMap and then to T in order to restrict the result set to a given T.
SELECT MAX(s.sNum)
FROM s
INNER JOIN S2TMap m on m.sID = s.sID
INNER JOIN t on t.tID = m.tID
WHERE t.tID = '000'
AND NOT EXISTS (
SELECT newID FROM temp WHERE temp.newID = s.sID
)

COUNT (DISTINCT column_name) Discrepancy vs. COUNT (column_name) in SQL Server 2008?

I'm running into a problem that's driving me nuts.
When running the query below, I get a count of 233,769
SELECT COUNT(distinct Member_List_Link.UserID)
FROM Member_List_Link with (nolock)
INNER JOIN MasterMembers with (nolock)
ON Member_List_Link.UserID = MasterMembers.UserID
WHERE MasterMembers.Active = 1 And
Member_List_Link.GroupID = 5 AND
MasterMembers.ValidUsers = 1 AND
Member_List_Link.Status = 1
But if I run the same query without the distinct keyword, I get a count of 233,748
SELECT COUNT(Member_List_Link.UserID)
FROM Member_List_Link with (nolock)
INNER JOIN MasterMembers with (nolock)
ON Member_List_Link.UserID = MasterMembers.UserID
WHERE MasterMembers.Active = 1 And Member_List_Link.GroupID = 5
AND MasterMembers.ValidUsers = 1 AND Member_List_Link.Status = 1
To test, I recreated all the tables and place them into temp tables and ran the queries again:
SELECT COUNT(distinct #Temp_Member_List_Link.UserID)
FROM #Temp_Member_List_Link with (nolock)
INNER JOIN #Temp_MasterMembers with (nolock)
ON #Temp_Member_List_Link.UserID = #Temp_MasterMembers.UserID
WHERE #Temp_MasterMembers.Active = 1 And
#Temp_Member_List_Link.GroupID = 5 AND
#Temp_MasterMembers.ValidUsers = 1 AND
#Temp_Member_List_Link.Status = 1
And without the distinct keyword
SELECT COUNT(#Temp_Member_List_Link.UserID)
FROM #Temp_Member_List_Link with (nolock)
INNER JOIN #Temp_MasterMembers with (nolock)
ON #Temp_Member_List_Link.UserID = #Temp_MasterMembers.UserID
WHERE #Temp_MasterMembers.Active = 1 And
#Temp_Member_List_Link.GroupID = 5 AND
#Temp_MasterMembers.ValidUsers = 1 AND
#Temp_Member_List_Link.Status = 1
On a side note, I recreated the temp tables by simply running (select * from Member_List_Link into #temp...)
And now when I check to see the difference between COUNT(column) vs. COUNT(distinct column) with these temp tables, I don't see any!
So why is there a discrepancy with the original tables?
I'm running SQL Server 2008 (Dev Edition).
UPDATE - Including statistics profile
PhysicalOp column only for the first query (without distinct)
NULL
Compute Scalar
Stream Aggregate
Clustered Index Seek
PhysicalOp column only for the first query (with distinct)
NULL
Compute Scalar
Stream Aggregate
Parallelism
Stream Aggregate
Hash Match
Hash Match
Bitmap
Parallelism
Index Seek
Parallelism
Clustered Index Scan
Rows and Executes for the 1st query (without distinct)
1 1
0 0
1 1
1 1
Rows and Executes for the 2nd query (with distinct)
Rows Executes
1 1
0 0
1 1
16 1
16 16
233767 16
233767 16
281901 16
281901 16
281901 16
234787 16
234787 16
Adding OPTION(MAXDOP 1) to the 2nd query (with distinct)
Rows Executes
1 1
0 0
1 1
233767 1
233767 1
281901 1
548396 1
And the resulting PhysicalOp
NULL
Compute Scalar
Stream Aggregate
Hash Match
Hash Match
Index Seek
Clustered Index Scan
FROM http://msdn.microsoft.com/en-us/library/ms187373.aspx
NOLOCK Is equivalent to READUNCOMMITTED. For more information, see READUNCOMMITTED later in this topic.
READUNCOMMITED will read rows twice if they are the subject of a transation- since both the roll foward and roll back rows exist within the database when the transaction is IN process.
By default all queries are read committed which excludes uncommitted rows
When you insert into a temp table the select will give you only committed rows - I believe this covers all the symptoms you are trying to explain
I think i have got the answer to your question but tell me first is userid a primary key in your original table ?
if yes,then CTAS query to create temp table would not copy any primary key of original table ,it only copy NOT NULL constraint that is not a part of primary key..fine?
now what happened your original table had a primary key so count(distinct column_name) doesnt include tuples with null records and while you created temp tables , primary key doesnt get copied and hence the NOT NULL constraint doesnt get to the temp table!!
is that clear to you?
It's hard to reproduce this behaviour, so I'm punching in the dark here:
The WITH (NOLOCK) statement enables reading of uncommitted data. I'm guessing you've added that to not lock anything for your users? If you remove those and issue a
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
Prior to executing the query, you should get more reliable results. But then, the tables may receive locks while executing the query.
If that doesn't work, my guess is that DISTINCT use an index to optimize. Check the queryplan, and rebuild indexes as necessary. Could be the source of your problem.
What result do you get with
SELECT count(*) FROM (
SELECT distinct Member_List_Link.UserID
FROM Member_List_Link with (nolock)
INNER JOIN MasterMembers with (nolock)
ON Member_List_Link.UserID = MasterMembers.UserID
WHERE MasterMembers.Active = 1 And
Member_List_Link.GroupID = 5 AND
MasterMembers.ValidUsers = 1 AND
Member_List_Link.Status = 1
) as m
AND WITH:
SELECT count(*) FROM (
SELECT distinct Member_List_Link.UserID
FROM Member_List_Link
INNER JOIN MasterMembers
ON Member_List_Link.UserID = MasterMembers.UserID
WHERE MasterMembers.Active = 1 And
Member_List_Link.GroupID = 5 AND
MasterMembers.ValidUsers = 1 AND
Member_List_Link.Status = 1
) as m
Ray, please try the following
SELECT COUNT(*)
FROM
(
SELECT Member_List_Link.UserID, ROW_NUMBER() OVER (PARTITION BY Member_List_Link.UserID ORDER BY (SELECT NULL)) N
FROM Member_List_Link with (nolock)
INNER JOIN MasterMembers with (nolock)
ON Member_List_Link.UserID = MasterMembers.UserID
WHERE MasterMembers.Active = 1 And
Member_List_Link.GroupID = 5 AND
MasterMembers.ValidUsers = 1 AND
Member_List_Link.Status = 1
) A
WHERE N = 1
when you use count with distinct column it doesn't count columns having values null.
create table #tmp(name char(4) null)
insert into #tmp values(null)
insert into #tmp values(null)
insert into #tmp values("AAA")
Query:-
1> select count(*) from #tmp
2> go
3
1> select count(distinct name) from #tmp
2> go
1
1> select distinct name from #tmp
2> go
name
NULL
AAA
but it works in derived table
1> select count(*) from ( select distinct name from #tmp) a
2> go
2
Note:- I tested it in Sybase