views:

482

answers:

2

I have an SQL table that looks like:

TABLE QUEUE
    ID
    DATA
    POSITION

Field POSITION holds the potition of the record relative to a Queue. So, it can be:

  • 0 not in any position (not queued).
  • 1 first in the queue (next in line).
  • > 1 the position in the queue.

I need a (MS) SQL query that will move the queue up one position.

Before the query:

  • 09, Record data 09, 0
  • 10, Record data 10, 1
  • 11, Record data 11, 2
  • 12, Record data 12, 3

After the query:

  • 09, Record data 09, 0
  • 10, Record data 10, 0
  • 11, Record data 11, 1
  • 12, Record data 12, 2

How can I do it in a single query?

+4  A: 
UPDATE QUEUE
SET POSITION = POSITION - 1
WHERE POSITION <> 0
John Saunders
They asked for a SQL query. I would consider yours to be a SQL statement.
onedaywhen
Define "query" vs. "statement".
John Saunders
A "query" returns a resultset.
onedaywhen
@onedaywhen: Fascinating. I was unaware of such a distinction. I wonder if it's used consistently. I think it's not, and I think it doesn't matter, and I doubt very much if that's what the OP was asking about.
John Saunders
An UPDATE is a query as defined by the SQL standard. Onedaywhen probably means the distinction between expressions and statements, http://stackoverflow.com/questions/19132/expression-versus-statement
Andomar
@Andomar: No, I don't means the distinction between expressions and statements. Which SQL Standard? From the SQL-92 Standard:7.9 <query specification>: Function: Specify a table derived from the result of a <table expression>. 13.9 <update statement: positioned>: Function: Update a row of a table.13.10 <update statement: searched>: Function: Update rows of a table.
onedaywhen
@John Saunders: have you used MS Access, perchance? In the ACE/Jet layer, if you create a VIEW (which must obviously consist of a SELECT query), it is exposed to MS Access as a Query object; however, if you create a PROCEDURE consisting of an UPDATE statement, it too is exposed to MS Access as a Query object. The Access documentation extensively refers to an 'update query'.
onedaywhen
Just found this newsgroup post from Joe Celko, who co-wrote the SQL-92 Standard: "Confusingly, the Access community refers to SQL DML statements as 'queries', hence terms such as 'delete query' are oxymoron to the wider SQL community." (http://help.lockergnome.com/office2/Sort-SQL--ftopict772132.html) Seems to support what I was saying quite well :)
onedaywhen
@John Saunders: "I think it doesn't matter" -- well, a query (as defined by the SQL-92 Standard) cannot change the underlying data, whereas an UPDATE statement can, so the distinction is not insignificant :)
onedaywhen
@onedaywhen: did you really think that the OP actually was referring to the same sources as you when he used the term "query"? Do you think he actually meant to exclude "UPDATE"? Then where's _your_ answer that updates the database using a "query"?
John Saunders
@John Saunders: "Then where's _your_ answer that updates the database using a 'query'?" Who said anything about updating the database? I think you are extrapolating too far :) No need for me to duplicate what Quassnoi posted (which I have upvoted).
onedaywhen
@John Saunders: "did you really think that the OP actually was referring to the same sources as you when he used the term 'query'?" -- my source is the aforementioned 'wider SQL community', so the answer to your question is, "yes."
onedaywhen
@onedaywhen: My answer is the one we're commenting on. I don't see any reason to believe that the OP or anyone else in the world besides you wants to limit the discussion to resultset-returning commands. If I found that the OP meant to limit it, I'd tell him to add an OUTPUT clause into a table variable, then add SELECT @variable after the UPDATE.
John Saunders
@onedaywhen: Other than those attempting to be pedantic, I have not noticed the "wider SQL community" having any consensus on this distinction in terms. For instance, you're the only person to attempt to "correct" my use of the term "query" here. I can't recall seeing anyone else (or even you) attempting to correct usage of the term "query" in an attempt to enforce the community consensus. I think it may possibly matter to experts, but maybe not to people just using SQL for a living.
John Saunders
@John Saunders: "pedantic" = pejorative. I prefer "unambiguous" or "formal".
onedaywhen
@Pedantic: was meant to be pejorative, because neither unambiguous nor formal were either necessary or desired. If you prefer, "pedantic, absent a pedagogical scenario, is pejorative".
John Saunders
@John Saunders: when I "corrected" your use of "pedantic" my tongue was firmly embedded in my cheek. I was aiming for irony. Is that "unambiguous" enough for you? ;-)
onedaywhen
If I asked the question, "Is a SQL UPDATE statement a 'query'" on SO I'm pretty sure it would soon be closed as "Not a programming question." So, agreed, no biggie. I was genuinely surprised that someone would post an UPDATE statement when the question specified, "a single query". I up vote the answer I think answers the question, I leave a comment against the one I think misunderstood and answer questions further with citations. Isn't that how SO works? I can post comments without posting an answer myself and hold a difference of opinion to you without being called a pejorative name, right?
onedaywhen
99.99% of the developers in the world would have included "UPDATE" as part of what the OP intended when he asked about a query. For those developers, including the OP, if they had meant only queries returning a result, they would have said "queries returning a result set". The fact that Joe Celko and the ANSI Committee don't include "UPDATE" under "query" is not relevant to the solution of actual problems in the actual, real, world. Nobody else cares, except for you, Joe Celko, and the ANSI SQL Committee. The latter two don't post here.
John Saunders
Truly, I'm open minded here. I really don't know how I came to my understanding of "UPDATE <> query." But when challenged I came up with the spec for the SQL-92 standard and the author of a dozen or so SQL books. Credible sources, I'd say. Now, may I challenge you to come up with some citations for your claims, please? I'd wager you just made that "99.99%" figure up.
onedaywhen
@onedaywhen: In 30 years of development, I've never met anyone but you appear to use the term "query" in a way that excludes an "update". Simple as that. Mind you, I haven't been back in school for most of those 30 years, which may be why I haven't heard such a distinction that is useless except to academics and standards developers. See also http://msdn.microsoft.com/en-us/library/ms177564.aspx, where an UPDATE with OUTPUT INTO @T may be followed int the same batch by SELECT * FROM @T, turning the statment into a query.
John Saunders
Thanks for the link (at last, a reference from you!): "Returns information from, or expressions based on, each row affected by an INSERT, UPDATE, DELETE, or MERGE statement." Not "query" then? Same site for UPDATE keyword only mentions "query" in the context of the CTE. Wikipedia entry for SQL UPDATE doesn't mention "query". I could go on but it's time to stop. You present you opinions as fact with nothing to back them up.
onedaywhen
@onedaywhen: that was not meant to argue about any idiot distinction between "query" and "not query". It was meant to show you how a statement sequence beginning with "UPDATE" could still return rows.
John Saunders
+1  A: 

Create your queue as a linked list:

id  parent

09  00
10  09
11  10
12  11

, and query like this:

WITH vq (id, position) AS (
     SELECT  id, 1
     FROM    queue
     WHERE   parent = 0
     UNION ALL
     SELECT  id, v.position + 1
     FROM    queue q, vq v
     WHERE   q.parent = v.id
     )
SELECT  *
FROM    vq

To remove an element from the queue, just update its parent to -1.

This is more efficient than updating all positions of all records in the table.

Quassnoi
Works as long as you don't hit the recursion limit. Of course, the recursion limit can be increased, but I guess it's there for a reason.
erikkallen
Unlike Oracle, SQL Server cannot dump the recursion stack into the tablespace, that's the reason for the limit. But queue queries don't tend to be large, since you normally don't need all the records at once, only top 10 maybe.
Quassnoi