SQL Update with select MIN from specific group in one table - sql

Im really new to SQL. I searched for an answer that would match my requirements AND I would understand what has been done- I failed obv. So here it goes:
I am making a programm that would keep data for marathon tournament. So I have a table StageResults with columns: StageNo ParticipantNumber ParticipantGroup Time(as in distance time in full sec's thus int) and Points
An example would look like:
- 1|01|M21|500|X
- 1|22|M21|550|X
- 1|45|M21|530|X
- 1|47|F09|600|X
- 1|09|F09|630|X
- 2|01|M21|515|X
- 2|45|M21|520|X
So I want the fastest member of each group in each stage to get 1000 points. In the back of my head I feel, that I could just write 1 single query for this, I tried for several hours.
Best that I have right now is this:
SELECT c1.ParticipantNumber, c1.ParticipantGroup, c1.Time
FROM StageResults AS c1
LEFT JOIN StageResults AS c2
ON c1.StageNo = c2.StageNo
AND c1.ParticipantGroup = c2.ParticipantGroup
AND c1.Time < c2.Time;
I used this under INSERT statement. No syntax errors but error, that I am trying to insert a duplicate primary key. I think this can be solved by adding GROUP BY statement. So I havent really tested this.
I would ultimately like to set 1000 points for fastest participant in each run(stage) and each group(I mean it should happen automatically). And then based on the fastest guy, calculate points for all other guys.(But thats later and if i figure out how to add these 1k pts, I think ill manage)
So I have to add this logic inside UPDATE statement. I am not able to. Im just lost.
Any advice is welcome. Maybe im thinking in the wrong direction completely on how to do this.
Any help will be much appreciated.

The query that identifies the rows might look like this:
select t.*
from table t
where not exists (select 1
from table t2
where t2.ParticipantGroup = t.ParticipantGroup and
t2.StageNo = t.StageNo and
t2.time < t.time
);
The question is then how you turn this into an update. For MySQL, you would do:
update table StageResults sr join
(select t.*
from table t
where not exists (select 1
from table t2
where t2.ParticipantGroup = t.ParticipantGroup and
t2.StageNo = t.StageNo and
t2.time < t.time
)
) toupdate
on toupdate.ParticpantNumber = sr.ParticpantNumber
set sr.points = sr.points + 1000;
The syntax for SQL Server would be a bit different, but your question is tagged MySQL.
EDIT:
For SQL Server:
with toupdate as (select t.*
from table t
where not exists (select 1
from table t2
where t2.ParticipantGroup = t.ParticipantGroup and
t2.StageNo = t.StageNo and
t2.time < t.time
)
)
update toupdate
set points = points + 1000;

Related

create and calculate z score column in SQL (mariadb)

As the title says, looking for a simple way to calculate the z score for each row in a column.
I tried the following, and don't know why it doesn't work (returns error ER_INVALID_GROUP_FUNC_USE)
ALTER TABLE tbl
ADD z_score INT;
UPDATE tbl
SET z_score = (values - avg(values))/ stddev(values)
WHERE values IS NOT NULL;
I've seen ways of doing it online, but they feel more complicated than is necessary.
In order to calculate the z-score, you need the average and standard deviation. You don't specify the database you are using, but one method that should work in (almost) all databases is a subquery:
UPDATE tbl
SET z_score = (SELECT (tbl.values - avg(tbl2.values)) / stddev(tbl2.values)
FROM tbl tbl2
)
WHERE values IS NOT NULL;
Most databases also support some sort of JOIN operation in the UPDATE, but the syntax depends on the database.
EDIT:
MariaDB does not support the above Standard SQL syntax. Instead, you can use a CROSS JOIN:
UPDATE tbl CROSS JOIN
(SELECT AVG(values) as avg_values, STDDEV(values) as stddev_values
FROM tbl
) t2
SET tbl2.z_score = (tbl.values - avg_values) / NULLIF(stddev_values, 0)
WHERE values IS NOT NULL AND stddev_values <> 0;

Delete query in SQL (Access) in conjuction with dependent data?

I know this is a very basic question but I am unable to get it done. Just started to learn more about databases. I have two tables: tblFoodAllowance and tblTravelDays.
tblFoodAllowance consists of ID, tripID, dateDay, costs.
tblTravelDay saves all days when I was on a business trip: ID, dateDay.
I am looking for a delete query in SQL to use in MS Access which does this: Delete all from tblFoodAllowance where tripID is xy (e.g. 1) and tblFoodAllowance.dateDay is not in the list of tblTravelDates. How can I achieve this?
I tried multiple things but either I got a syntax error or a wrong result. Thanks for your help.
I guess it is something like:
DELETE * FROM tblFoodAllowance WHERE tblFoodAllowance.tripID = [tripID] and ()
You can use delete:
delete from tblFoodAllowance
where tripID = #xy and
not exists (select 1
from tblTravelDates
where tblTravelDates.tripId = tblFoodAllowance.tripId and
tblTravelDates.dateDay = tblFoodAllowance.dateDay
);
Consider using not exists and a correlated subquery. It is a bit unclear exactly which colums connect the two tables, but the idea is:
delete from tblFoodAllowance
where
tripID = 1
and not exists (
select 1
from tblTravelDay
where tblTravelDay.dateDay = tblFoodAllowance.dateDay
)

UPDATE SQL column based on values of another column. (It's not that simple)

I am trying to update a column with a value of a different column under certain circumstances. It's complicated. I've tried to figure this out on my own for a weeks now. (on and off)
Here is how it currently looks:
I Need a SQL statement that will look for the LotNo at OperationCode 1280 and assign it for all values with the same CastTID.
Here is what it should look like after
I would really appreciate any help! This is my first post, if iv'e left out anything important please let me know so that I can help you help me.
You can use a join in your update statement to make this easier.
update t
set CastLotNo = t2.LotNo
from yourTable t
inner join yourTable t2 on t2.CastTID = t.CastTID and t2.OperationCode = 1280
UPDATE `myTable` SET `CastLotNo` = (SELECT `LotNo` FROM `MyTable` WHERE `OperationCode` = '1280' LIMIT 1) WHERE `CastTID` = (SELECT `CastTID` FROM `MyTable` WHERE `OperationCode` = '1280' LIMIT 1)
It seems like you could use something like that. I can't test this at the moment, so let me know if it needs tweaking.
WITH cte as (
SELECT CastTID, LotNo
FROM Table1
WHERE OperationCode = 1280
)
UPDATE myTable T
SET CastLotNo = (SELECT C.LotNo as CastLotNo
FROM cte C
WHERE C.CastTID = T.CastTID)

SELECT query to return a row from a table with all values set to Null

I need to make a query but get the value in every field empty. Gordon Linoff give me the clue to this need here:
SQL Empty query results
which is:
select t.*
from (select 1 as val
) v left outer join
table t
on 1 = 0;
This query wors perfectly on PostgreSQL but gets an error when trying to execute it in Microsoft Access, it says that 1 = 0 expression is not admitted. How could it be fixed to work on microsoft access?
Regards,
If the table has a numeric primary key column whose values are non-negative then the following query will work in Access. The primary key field is [ID].
SELECT t2.*
FROM
myTable AS t2
RIGHT JOIN
(
SELECT TOP 1 (ID * -1) AS badID
FROM myTable AS t1
) AS rowStubs
ON t2.ID = rowStubs.badID
This was tested with Access 2010.
I am offering this answer here, even though you didn't think it worked in my edit to your original question. What is the problem?
select t.*
from (select max(col) as maxval from table as t
) as v left join
table as t
on v.val < t.col;
You can use the following query, but it would still need a little "manual coding".
EDITS:
Actually, you do not need the SWITCH function. Modified query below.
Removed the reference to Description column from one line. Still, you would need to use a Text column name (such as Description) in the last line of the query.
For example, the following query would work for the Months table:
select Months.*
from Months
RIGHT OUTER JOIN
(select "" as DummyColumn from Months) Blank_Data
ON Months.Description = Blank_Data.DummyColumn; --hardcoded Description column

SQL Sybase Query Strange Behaviour

I've got 2 tables with exactly the same structure in the same Sybase database but they're separate tables.
This query works on one of the 2:
select * from table1 where
QUOTA_FIELD >
(SELECT
count(ACCOUNT) FROM
table1 As t1
where SECTOR = t1.SECTOR
AND
STATUS = 'QUOTA'
)
But for the second table I have to change it to this:
select * from table2 as tref where
QUOTA_FIELD >
(SELECT
count(ACCOUNT) FROM
table2 As t2
where tref.SECTOR = t2.SECTOR
AND
STATUS = 'QUOTA'
)
There's a restriction on where this will execute which means it needs to work like in the first query.
Does anyone have any ideas as to why the first might work as expected and the second wouldn't?
Since I am not yet allowed to comment, here as an answer to the question "does anyone...?":
No. I couldn't find anyone :)
This first query cannot work correctly, since it compares a column with itself (as long as the column names are all normal ASCII characters and not some similar looking UNICODE ones). Please give a proof that the result of this query is in every case the same as of query 2.
Also, the second query would normally be done like that: where SECTOR = tref.SECTOR...
You might be looking for something like this in query #1 :
select * from table1 t2 where
QUOTA_FIELD >
(SELECT
count(ACCOUNT) FROM
table1 As t1
where t2.SECTOR = t1.SECTOR
AND
t1.STATUS = 'QUOTA'
)
This explicitly specifies that the table in subquery is joining with the table in outer query ( co-related subquery ).
If this works, use the same idea in query #2