UPDATE or SET from a SELECT query? - sql

I have a database of information that should only be used one time. To grab the information to be exported into a .CSV file for use. I would use the following query, we also have the column USED which should be set to YES after the data has been exported (so it not re-used).
SELECT TOP(40000)
ms.website AS Website,
ms.company AS COMPANY,
ms.address AS [ADDRESS],
ms.city AS CITY,
ms.state AS [STATE],
ms.zip AS ZIP,
ms.phone AS PHONE
FROM
[QUETABLE] as ms
WHERE
DEAD != 'YES' AND USED != 'YES';
And then I figured I would use this query to update the column "USED" so that if the same query was run again, only new information would be exported:
UPDATE TOP(40000) QUETABLE
SET USED = 'YES'
WHERE USED = 'NULL' AND DEAD != 'YES';
However, while a lot of the data was the same, for some reason, not all 40,0000 columns were matching, meaning un-used data would be marked as used (and vice versa), the USED column is set to NULL before its used (not IS NULL, but written "null').
How could I run the top query, but at the same time also set USED to "YES" so the information is identical? So, in broken SQL it would be like:
SELECT TOP(40000)
ms.website AS Website,
ms.company AS COMPANY,
ms.address AS [ADDRESS],
ms.city AS CITY,
ms.state AS [STATE],
ms.zip AS ZIP,
ms.phone AS PHONE
FROM [QUETABLE] as ms
WHERE DEAD != 'YES' AND USED != 'YES' THEN SET USED = 'YES';
But of course, that wouldn't work, I'm not sure how to accomplish this!
Thank you

You are using TOP with no ORDER BY. This returns an arbitrary set of rows. There is no reason to think that the rows returned on two different runs of the same query would return the same rows, much less an UPDATE and a SELECT.
I would suggest that you use the OUTPUT clause and do the work in the opposite order:
DECLARE #t TABLE ( . . . ); -- fill in the columns
UPDATE TOP(40000) QUETABLE
SET USED = 'YES'
OUTPUT inserted.* INTO #t;
WHERE USED = 'NULL' AND DEAD <> 'YES'
Now you can "export" the ones that were just set to DONE.

Related

Error with syntax replacing values in the query output

I work within the SQL database, but am self taught, so there are a few holes in my knowledge. I have this query that although I would think is simple, I just cant get it right.
I have two columns, one with a 'Name', and the other 'Privacy'.
I am trying to to get a result where if the Privacy column has a numerical value (3) in it, all these rows will return a 'name suppressed' in the Name column. And all the rows with a NULL in the Privacy column are left alone.
But I don't want to update the database, just suppress the name in the query.
I have tried, replace, case, if then and a few more with no luck. Can someone please help me.
Thanks
Michele
You can go for simple CASE expression. I am assuming you only want to suppress if privacy = 3.
SELECT CASE WHEN Privacy = 3 THEN 'Name Suppressed'
ELSE Name
END AS Name, Privacy
FROM TableName
SELECT
CASE
WHEN [Privacy] IS NULL THEN [Name]
ELSE N'name suppressed'
END AS [Name],
[Privacy]
FROM
[dbo].[YourTable]

T-SQL Skip cte Table and Union when Variable Is Null

I've got a query that captures all shipments and costs from our factory. Sample data and desired output on Google Drive here:
https://drive.google.com/open?id=0B4xdnV0LFZI1VndEaGgxNDVpU2M
The issue is we've got 2 different ways of selling things. One is 'Regluar' where we make it and the other one is a 'buy/sell' where we buy and sell it.
To capture the costs I've had to write two queries, one for each scenario. The end users of this query can enter in a date range and the query works well then, but I'm stuck when it comes to the variable #Job_No.
All work that goes through our factory (cteRegularJobs) has a Job Number associated with it and I've declared a variable so users can use it to search. The cteBuyandSell has a value of 'NULL' for Job_No declared in the SELECT statement so I can do a UNION of these two tables at the end. However, no buy/sell jobs have Job Numbers assigned to them, they are always NULL.
Initially #Job_No is declared as '' and when it's left '' I want the results from both cte tables returned. If there is an entry by the user, i.e. '001' then I want results for cteRegularJobs.
If it makes it easier I am open to declaring the cteBuyandSell.Job_No something else besides NULL, like "Buy and Sell".
The real query is complicated so here's a simplified example of the structure:
DELCARE #Job_No AS varchar(10) = '';
SET #Job_No = {User Input or leave as ''};
WITH
cteBuyandSell AS ( NULL AS 'Job_No',
...),
cteRegularJobs AS (tblJobs.Job_No AS 'Job_No',
...
WHERE tblJobs.Job_No LIKE #Job_No)
SELECT *
FROM
(cteBuyandSell
UNION
cteRegularJobs)
You can logically break this up with an IF statement to check the value of your variable. I'd suggest NULL over white space though. Here's an example procedure... with the limited code you provided.
CREATE PROCEDURE getData(#Job_No varchar(10) = NULL)
AS
IF #Job_No IS NULL
BEGIN
WITH
cteBuyandSell AS ( NULL AS 'Job_No',
...),
cteRegularJobs AS (tblJobs.Job_No AS 'Job_No',
...
WHERE tblJobs.Job_No LIKE #Job_No)
SELECT *
FROM
(cteBuyandSell
UNION
cteRegularJobs)
END
ELSE
BEGIN
WITH
cteRegularJobs AS (tblJobs.Job_No AS 'Job_No',
...
WHERE tblJobs.Job_No LIKE #Job_No)
SELECT * FROM cteRetularJobs
END

How to use case statement to declare a local variable for a subsequent subquery?

Is it possible to declare a local variable depending on the case and then fire a common subquery?
Pseudo code:
SELECT
CASE
WHEN TABLE.TYPE = 'STUDENT' variable = "UNIVERSITY"
WHEN TABLE.TYPE = 'EMPLOYEE' variable = "EMPLOYER"
(Some big query here it has a common joins / groupings but the variable changes)
END AS NAME
FROM TABLE
Looking for a SQL Server solution.
Scenario is like this - I have a query that lists some member information . Now I need to get some addendum data to an existing query - I mean result set won't change . I can actually join but then I have to filter out many things - Does that make sense ? Imagine I was display all the members in the table and someone asks me to show the univeristy name or the employer name . And the biggest problem is a member can have more than one university he attended - same for employer . Isn't joins really bad on performance in this case ? Since there are many one to many stuff . Also please note I finally display only 10 records as part of pagination so I thought I should do a case statement .
DECLARE #variable varchar(10)
SELECT #variable =
CASE
WHEN t.TYPE = 'STUDENT' THEN 'UNIVERSITY'
WHEN t.TYPE = 'EMPLOYEE' THEN 'EMPLOYER'
ELSE 'Undefined'
END
FROM TableName t
MSDN - SELECT #local_variable
If the SELECT statement returns more than one value, the variable is
assigned the last value returned.

How to update a PostgreSQL table with a count of duplicate items

I found two bugs in a program that created a lot of duplicate values:
an 'index' was created instead of a 'unique index'
a duplication checks wasn't integrated in one of 4 twisted routines
So I need to go in and clean up my database.
Step one is to decorate the table with a count of all the duplicate values (next I'll look into finding the first value, and then migrating everything over )
The code below works, I just recall doing a similar "update from select count" on the same table years ago, and I did it in half as much code.
Is there a better way to write this?
UPDATE
shared_link
SET
is_duplicate_of_count = subquery.is_duplicate_of_count
FROM
(
SELECT
count(url) AS is_duplicate_of_count
, url
FROM
shared_link
WHERE
shared_link.url = url
GROUP BY
url
) AS subquery
WHERE
shared_link.url = subquery.url
;
You query is fine, generally, except for the pointless (but also harmless) WHERE clause in the subquery:
UPDATE shared_link
SET is_duplicate_of_count = subquery.is_duplicate_of_count
FROM (
SELECT url
, count(url) AS is_duplicate_of_count
FROM shared_link
-- WHERE shared_link.url = url
GROUP BY url
) AS subquery
WHERE shared_link.url = subquery.url;
The commented clause is the same as
WHERE shared_link.url = shared_link.url
and therefore only eliminating NULL values (because NULL = NULL is not TRUE), which is most probably neither intended nor needed in your setup.
Other than that you can only shorten your code further with aliases and shorter names:
UPDATE shared_link s
SET ct = u.ct
FROM (
SELECT url, count(url) AS ct
FROM shared_link
GROUP BY 1
) AS u
WHERE s.url = u.url;
In PostgreSQL 9.1 or later you might be able to do the whole operation (identify dupes, consolidate data, remove dupes) in one SQL statement with aggregate and window functions and data-modifying CTEs - thereby eliminating the need for an additional column to begin with.

How do I modify the hundards of records based on my query result?

I inserted some error record to my table, I can query via the sql below and found hundards of record marked with half.
SELECT * FROM `marathon`
WHERE gender = 'male' && distance = 'half';
How to write a SQL then I can modify the result rows distance from 'half' to 'full'.
Thank you.
update marathon
set distance = 'full'
WHERE gender = 'male' and distance = 'half';
read http://dev.mysql.com/doc/refman/5.0/en/update.html (mysql update syntax)
Thierry has the right answer, but I want share a technique I use when writing update statements:
update m
set distance = 'full'
--select marathon_id, gender, distance from
From marathon m
WHERE gender = 'male' and distance = 'half';
By embedding the select in the stamenet as a comment, you can check to see which records will be affected before running the update and if you are updating to a complex formula you can even see what the current and updated results would be. Even better if you already have the select statment, it's pretty easy to add the update parts on top of it. This also helps you see how your update relates directly to your select.