Scalar function taking so much time - sql-server-2008

I need someone who can tell me what I'm missing.
I have this scalar function in SQL Server 2008:
ALTER function [dbo].[SKU](#id1 int, #id2 int)
returns int
begin
return (
SELECT SUM(Value)
FROM Table
where id_1 = #id1
and id_2 = #id2)
end
And the table is like this:
id_1 id_2 Value
1004 1 10
1004 1 30
1004 2 100
1005 1 90
1005 1 5
1005 1 5
If I execute:
select [dbo].[SKU](1004,1)
it returns 40 - That's ok
select [dbo].[SKU](1004,2)
returns 100 - OK
select [dbo].[SKU](1005,1)
returns 100 - OK
At this point all seems ok, but my table has almost a millon rows... the result of SKU goes to the same table (update part).
But I ran it for two hours now, and is still running...
My question: I've never seen such as long time consuming query. It's ok? I'm missing something?
Thanks!, and happy new year ! D:

If changing the table design or programming to it is not an option, an easy solution would be to create a covering index on the fields you are using in your function.
Something like
CREATE INDEX IX_TABLE_ID_1_ID_2_VALUE ON dbo.Table (id_1, id_2) INCLUDE (Value)

This is not to be interpreted as an answer but an attempt to drill down to the real problem
Currently, this is as how I interpretate the actions that get executed
Starting from the initial table
id_1 id_2 Value Result
1004 1 10 NULL
1004 1 30 NULL
1004 2 100 NULL
1005 1 90 NULL
1005 1 5 NULL
1005 1 5 NULL
After update table set result = dbo.SKU(1004, 2) this would become
id_1 id_2 Value Result
1004 1 10 40
1004 1 30 40
1004 2 100 40
1005 1 90 40
1005 1 5 40
1005 1 5 40
After update table set result = dbo.SKU(1004, 1) this would become
id_1 id_2 Value Result
1004 1 10 100
1004 1 30 100
1004 2 100 100
1005 1 90 100
1005 1 5 100
1005 1 5 100
After update table set result = dbo.SKU(1005, 1) this would become (remain)
id_1 id_2 Value Result
1004 1 10 100
1004 1 30 100
1004 2 100 100
1005 1 90 100
1005 1 5 100
1005 1 5 100
and somehow after that, the result is divided by id_2
id_1 id_2 Value Result
1004 1 10 100
1004 1 30 100
1004 2 100 50
1005 1 90 100
1005 1 5 100
1005 1 5 100
Clearly, my interpretation and what really happens don't match (at least I hope so).

This might get you what you need a little quicker if you don't have to use a function.
;with sumVal
as
(
select t1.id_1, t1.id_2, SUM(t1.value) [result]
from [table] t1
group by t1.id_1, t1.id_2
)
select t2.*, s.result
from sumVal s
left join [table] t2 on s.id_1 = t2.id_1 and s.id_2 = t2.id_2
It ran in less than 5 seconds on over 800,000 rows on my test.

Related

Update the mysql field according to the sorting

a simple task, but I can't figure it out. There is a Table:
id
name
sum
place
1
Alex
210
0
2
Bob
250
0
3
Sam
190
0
4
Bill
290
0
5
Jack
210
0
I need to UPDATE the PLACE
according to the maximum SUM and then the id
Those are the request :
SELECT id, name, sum, place FROM tableORDER BYsumDESC,id ASC;
According to this request, update the semi PLACE from 1++
Those places 1, 2, 3 and further throughout the table
Like this:
id
name
sum
place
1
Alex
210
3
2
Bob
250
2
3
Sam
190
5
4
Bill
290
1
5
Jack
210
4
SET #n_place := 0;
UPDATE `table` SET `place` = #n_place := #n_place + 1 ORDER BY `sum` DESC, `id` ASC;

MySQL query using Update, Sum, Where, and Group By

I have a table below named deposit
dep_id
deposit_amount
comp_id
1
100
1
2
100
1
3
300
2
4
200
2
5
100
2
6
500
3
When I update the table with the query below I get the following table, which is not what I want
UPDATE deposit
SET deposit_amount = (SELECT SUM(deposit_amount) - 50)
WHERE comp_id =1
What the query above does is to subtract 50 from each of the corresponding comp_id
dep_id
deposit_amount
comp_id
1
50
1
2
50
1
3
300
2
4
200
2
5
100
2
6
509
3
But the table below is what I need.
Because seeing the first table and with the query I provided where comp_id =1, we have 100 + 100 = 200, and then 200 - 50 = 150. So because comp_id has 1 IDs two times, therefore we have 75 and 75 because 75 +75 is 150. So we have the table below, which is what I need.
dep_id
deposit_amount
comp_id
1
75
1
2
75
1
3
300
2
4
200
2
5
100
2
6
500
3
The amount supposed to be evenly split amongst the deposits that share a comp_id, even if they weren't before.
Please how do I write the query to suit the table I need? Help!
You can divide the 50 by the count of the records for this id:
UPDATE deposit d1,
(SELECT *, count(*) over (partition by d2.comp_id) as c FROM deposit d2) x
SET d1.deposit_amount = (SELECT SUM(d1.deposit_amount) - 50/x.c)
WHERE d1.comp_id =1
see: DBFIDDLE

Get max score and store in another column

This is my table:
student_id
subject_id
total
max
101
1
90
102
2
80
103
1
95
101
1
82
103
2
76
104
1
95
101
2
71
I want to get the max total in a particular subject and store it in another column whenever the total column is inserted or updated.
This is what I want the table to look like:
student_id
subject_id
total
max
101
1
90
95
102
2
80
80
103
1
95
95
101
1
82
95
103
2
76
80
104
1
95
95
101
2
71
80
I have tried this query but it doesn't add the max scores in each subject against all the student_id.
SELECT MAX(`total`) AS highest
FROM results
GROUP BY student_id
I suppose I should use a trigger for this but the normal query is also okay by me.
If your column does not yet exist in your table, you need to add it with an ALTER statement.
ALTER TABLE <your_table_name> ADD max INT;
Then you can first select the "max" value for each "subject_id" using an aggregation, then use it inside the UPDATE statement exploiting a JOIN operation:
UPDATE <your_table_name>
INNER JOIN (SELECT subject_id,
MAX(total) AS total_max
FROM <your_table_name>
GROUP BY subject_id) cte
ON <your_table_name>.subject_id = cte.subject_id
SET <your_table_name>.max = cte.total_max;
Check the demo here.
Assuming you are using MySQL 8+.
Ideally, instead of storing MaxTotal data into each column, you should get such the data while selecting like this:
WITH CTE AS (SELECT subject_id,MAX(total) AS MaxTotal
FROM results
GROUP BY subject_id
)
SELECT results.*,CTE.MaxTotal
FROM results
JOIN CTE ON results.subject_id = CTE.subject_id;
However, if you still need to update it anyway, use UPDATE with JOIN
WITH CTE AS (SELECT subject_id,MAX(total) AS MaxTotal
FROM results
GROUP BY subject_id
)
UPDATE results
JOIN CTE ON results.subject_id = CTE.subject_id
SET results.MaxTotal = CTE.MaxTotal;
Output after the update:
student_id
subject_id
total
MaxTotal
101
1
90
95
102
2
80
80
103
1
95
95
101
1
82
95
103
2
76
80
104
1
95
95
101
2
71
80
See this db<>fiddle.

GROUP BY using a SUM

This is a tough one to explain. I have this data set
Data set 1
counter | id
1 280
1 280
0 280
1 781
1 781
1 781
0 25
1 25
1 25
I want to GROUP BY the id, but with the SUM of counter so I end up with this data set
Data set 2
counted | id
2 280
3 781
2 25
I have tried a number of approaches but I always end up with the total SUM of rows for each ID like this
Data set 3
counted | id
3 280
3 781
3 25
EDIT
It might be worth noting that data set 1 comes from a sub query and is not a table in itself.
EDIT
I have used a query like this, it gives me the result of data set 3
select sum(counter) as counted, id
from t
group by id;
Did you do this?
select sum(counter) as counted, id
from t
group by id;

Excluding results and performing an insert with SQL query

Table a
Rowid Msgid Userid
1 3 55
2 3 56
3 3 57
4 4 55
5 4 56
Table Group
RowID GroupID UseriD
1 2 55
2 2 56
3 2 57
4 2 58
5 2 59
6 2 60
7 3 60
8 3 55
Here there is a table a and group table. Rowid primary keys
I want to insert rows into table a
This query will
Insert rows into table a i.e for msgid 3 there is already 55 56 57 so it has to insert only 58 59 60.
Insert into
table a (msgid,Userid)
values(#msgid,#userid)
where userid not in table a
where tbl_a.msgid=3
and tbl_group.groupid = 2
For Msgid 3 I want to check if there are any group members (groupID 2) associated in table a, if not then add a row to it.
ie add to table a
rowid Msgid Userid
6 3 58
7 3 59
8 3 60
So I wont insert the userid 55,56,57 because it is already in the table a for msgid 3. How to do a query for this scenario
Try below code
Insert IGNORE into
table a (msgid,Userid)
values(#msgid,#userid)
where userid not in table a
where tbl_a.msgid=3
and tbl_group.groupid = 2
I am considering that your insert query is correct...
Good Luck!!!
It's actually quite simple:
INSERT INTO TABLE_GROUP
SELECT * FROM TABLE_A
WHERE ... -- you can have or not have a where clause as you like
ON DUPLICATE KEY UPDATE;