TRANSACT SQL - How to manually order/index a table based upon a select/where statement - sql

I have sql puzzler today.
I have the following sql :
SELECT MemberId,
UnitId,
MaterialLevel,
MaterialText,
ProductPercentage,
ProductPriority
FROM tblWeights
ORDER BY MemberId, MaterialLevel, MaterialText, ProductPercentage DESC
Now, currently the ProductPriority is empty. What I would like to do is update this so that the first product, per level, per materialtext with the highest product percentage with "1", the second highest percentage with "2", etc, etc.
However, when the materialtext changes, this should reset itself and and start again at "1".
Can anyone think how I can do this?

Is there any reason you want productpriority explicitly stored in the database? Sorry if I've misunderstood your question but this sounds like it could be handled with a straight ROW_NUMBER in the output query.

You can use this for the initial update:
UPDATE tblWeights w1
SET ProductPriority = (
SELECT COUNT(*)
FROM tblWeights w2
WHERE w2.level = w1.level
AND w2.materialText = w1.materialText
AND w2.ProductPercentage >= w1.ProductPercentage
)
For the automatic reset, you should probably write a trigger that fires at the statement level after DELETE, UPDATE and INSERT. You can use a modified version of this statement, and only update the rows having the affected level,materialtext combination
CREATE TRIGGER aiud_tblWeights ON tblWeights
FOR INSERT, UPDATE, DELETE
AS
IF( UPDATE (Level) OR UPDATE (MaterialText) )
BEGIN
UPDATE tblWeights w1
SET ProductPriority = (
SELECT COUNT(*)
FROM tblWeights w2
WHERE w2.level = w1.level
AND w2.materialText = w1.materialText
AND w2.ProductPercentage >= w1.ProductPercentage
)
WHERE (w1.level, w1.materialText) IN (
SELECT level, materialText
FROM inserted
UNION ALL
SELECT level, materialText
FROM deleted
);
END;

I know its too late. but I found one answer when I was looking for similar questions for my help. see if helps someone else.
SQL query results to be displayed in the order of the manually provided values

Related

Can you run an UPDATE and WITH together?

I am trying to run an update on a table, but get an error
ERROR: syntax error at or near "UPDATE"
The query is:
WITH
first_users AS (
select min(created_at) as first_at,
company_id as company_id
from users
group by company_id
)
UPDATE companies
SET first_seen_at = LEAST(first_seen_at,
(SELECT first_at FROM first_users WHERE id = first_users.company_id)
);
Can you not run UPDATEs and WITHs together? Seems weird.
My query is actually slightly more complex, which is why I am using the with syntax. When I run SELECT * FROM first_users instead of UPDATE, it works, so there's something wrong with the UPDATE keyword or something.
I would suggest changing this to an update . . . from in any case. There is no reason to update records that do not match. So:
update companies
set first_seen_at = u.first_at
from (select company_id, min(created_at) as first_at
from users
group by company_id
) u
where companies.id = u.company_id and
u.first_seen_at < companies.first_seen_at;
Postgres started supporting CTEs with updates in version 9.1 (http://www.postgresql.org/docs/9.1/static/sql-update.html vs http://www.postgresql.org/docs/9.0/static/sql-update.html). This method is better because it filters the rows before the update.
Try encapsulating the query qith BEGIN/END. I don't know about PostgreSql, but MsSql does not accept WITH without BEGIN/END...

sql server if statement not working

Can anyone advise me as to what is wrong with the following SQL server update statement:
IF (SELECT * FROM TBL_SystemParameter WHERE code='SOUND_WRONG_GARMENT') = ''
GO
UPDATE TBL_SystemParameter
SET [Value] = 'Ping.wav'
WHERE ID = (SELECT ID
FROM TBL_SystemParameter
WHERE code = 'SOUND_WRONG_GARMENT')
You don't need an if statement - you can just run the update statement, and if the subquery returns no rows, no rows will be updated. The if won't really save anything - you're performing two queries instead of one.
You either want
UPDATE TBL_SystemParameter
SET [Value] = 'Ping.wav'
WHERE ID In (SELECT ID
FROM TBL_SystemParameter
WHERE code = 'SOUND_WRONG_GARMENT')
if there are multiple ID's with that code OR use
UPDATE TBL_SystemParameter
SET [Value] = 'Ping.wav'
WHERE code = 'SOUND_WRONG_GARMENT'
either way and lose the IF statement as #Mureinik said.
Although Mureinik's answer is the logical solution to this, I will answer why this isn't actually working. Your condition is wrong, and this approach will work instead using IF EXISTS:
IF EXISTS (SELECT * FROM TBL_SystemParameter WHERE code='SOUND_WRONG_GARMENT')
BEGIN
UPDATE TBL_SystemParameter
SET [Value] = 'Ping.wav'
WHERE ID IN (SELECT ID
FROM TBL_SystemParameter
WHERE code = 'SOUND_WRONG_GARMENT')
END
As a side note, you're using an = sign instead of IN, which means you'll be matching to an arbitrary singular ID and only update 1 row based on this. To use a set based operation, use the IN clause.
You could actually 'golf' this by doing away with the derived query altogether, and using a simple WHERE code='SOUND_WRONG_GARMENT' on the table you're updating on.

Oracle SQL update

I've tried searching for this particular topic here, but haven't found the answer... Anyway, my aim is to update table (let's call it t_item), specifically column owner_id with values depending on another table (t_item_geo which is in turn linked to t_geo).
I'm not entirely sure whether the syntax below is actually valid for update statements.
UPDATE t_item SET owner_id= 6993 WHERE t_item.owner_id in
(SELECT t_item.owner_id FROM
t_item,
t_item_geo,
t_geo
WHERE
t_item.id = t_item_geo.item_id and
t_item_geo.geo_id = t_geo.id and
t_item.owner_id in (SELECT id FROM t_user WHERE network_id='fffffff') and
t_geo.id in (SELECT id FROM t_geo WHERE full_name = 'yyyyyyy')
);
Anyway, my problem with this query is that it updates far more rows than it should - if I separate just the select statement Oracle returns ~750 rows but the udpate itself updates more than 4000 rows. It's almost as if the condition was completely ignored - which would point me to perhaps incorrect syntax.
I need to update specific value in the table based on the select from few other 'joined' tables. Hope it makes sense.
Thanks for any contribution!
UPDATE: sorry - maybe it wasn't clear from the question itself, but the correct number of edited items should be ~750 and not ~4000. Thanks!
try this
MERGE INTO t_item
USING
(
SELECT t_item.owner_id FROM
t_item,
t_item_geo,
t_geo,
t_item.rowid rowid_sub
WHERE
t_item.id = t_item_geo.item_id and
t_item_geo.geo_id = t_geo.id and
t_item.owner_id in (SELECT id FROM t_user WHERE network_id='fffffff') and
t_geo.id in (SELECT id FROM t_geo WHERE full_name = 'yyyyyyy')
) on (rowid = rowid_sub)
WHEN MATCHED THEN
UPDATE SET owner_id= 6993;

Sql Server CE can I delete TOP or only 1 record from table that matches my query

select Top(1)* from TableName Where columnName=value
selects only the first row just fine. However if I change the select to a delete I get an error and can't figure out how to write a query to delete only 1 record that matches my query from the db.
I'm wondering if anybody out there smarter than I knows if or how this can be done in SQL CE.
Did you try something like this?
DELETE TableName where IdColumn In ( select Top(1) IdColumn from TableName Where columnName=valuev)
I don't know specifically as I'm at home, but SQL CE is deliberately restricted in what it can do. One reason for this is that it is 'always' running locally to the process referencing it.
What means is that it is Expected that the other process is expected to handle much of the logic that may otherwise be encapsulated in the SQL Server. This often results in firing several queries at the SQL CE instance, where you may be more accustomed to firing off one.
In this case, you could do it with two queries...
1) A query to identify the record that you want to delete
2) Use that Identifier in another query to do the actual delete
You could also try using SET ROWCOUNT 1 to limit the DELETE to just 1 row. But again, I don't know if that works in CE.
You can use CTE such as
;with myTopRow(rowID)
(
select Top 1 rowID from TableName Where columnName=value
)
delete from TableName inner join myTopRow on TableName.rowID = myTopRow.rowID
Shouldn't it be rather :
DELETE FROM TableName WHERE columnName=value ORDER BY columnName LIMIT 1;
IMHO, the table logically has NO order by itself. It has it physically, but you can't rely on it. So, you HAVE to set the order in which you want to delete the first row.
The following code will delete only first row
Dim mySqlCommondDelete As String = "DELETE BOOK_ID, MemberID FROM (SELECT TOP 1 * FROM ISSUE_BOOK) where BOOK_ID = Val(" & deleteBook & ") and MemberID = Val(" & msk & ")"

Updating a table within a select statement

Is there any way to update a table within the select_expr part of a mysql select query. Here is an example of what I am trying to achieve:
SELECT id, name, (UPDATE tbl2 SET currname = tbl.name WHERE tbl2.id = tbl.id) FROM tbl;
This gives me an error in mysql, but I dont see why this shouldn't be possible as long as I am not changing tbl.
Edit:
I will clarify why I cant use an ordinary construct for this.
Here is the more complex example of the problem which I am working on:
SELECT id, (SELECT #var = col1 FROM tbl2), #var := #var+1,
(UPDATE tbl2 SET col1 = #var) FROM tbl WHERE ...
So I am basically in a situation where I am incrementing a variable during the select statement and want to reflect this change as I am selecting the rows as I am using the value of this variable during the execution. The example given here can probably be implemented with other means, but the real example, which I wont post here due to there being too much unnecessary code, needs this functionality.
If your goal is to update tbl2 every time you query tbl1, then the best way to do that is to create a stored procedure to do it and wrap it in a transaction, possibly changing isolation levels if atomicity is needed.
You can't nest updates in selects.
What results do you want? The results of the select, or of the update.
If you want to update based on the results of a query you can do it like this:
update table1 set value1 = x.value1 from (select value1, id from table2 where value1 = something) as x where id = x.id
START TRANSACTION;
-- Let's get the current value
SELECT value FROM counters WHERE id = 1 FOR UPDATE;
-- Increment the counter
UPDATE counters SET value = value + 1 WHERE id = 1;
COMMIT;