This question already has answers here:
Simplifying a query with a nested query
(3 answers)
Closed 1 year ago.
How to create a single MSSQL SELECT query in this case:
We've got 2 tables: fruits and expiration
The goal is to receive table where specific fruit number has information about having NULL in expirationDate column. Those fruit numbers that don't have NULL would have zeros in that column. Number 4 doesn't exist in expiration table, so it would also have 0 in results, because it doesn't have NULL.
Tables
You can't easily get the expiration date on the format you want. However, it does not really matter(?). I assume you want 1 or 0 in your new table because you want to use an if statement to check if the fruit is bad or not.
You can solve this easily:
if(expirationDate == null){/*something*/}
or, you might even be able to do
if(expirationDate) //this is all fruit that is not bad
else{/*your code to deal with expirated fruit here*/}
Note: I don't know what programming languages you are using. But in most of them: null and 0 are FALSE.
if(null) // false
if(0) //false
if(undefined) //false, in javascript
//everything that is not a false value, is true.
if("oiaehgtaoiwgneawg") //true
if(-1) //true
To answer your SQL query question:
You already have everything you need in the expiration table
SELECT fruit_number, expiration_date
FROM expiration;
I hope this helps 😊
You have to use it with Case Condition. But have to change statement a little:
select fruit_number, --distinct(fruit_number),
x =case expiration_date
when NULL then null
else 0
end
My friend found the solution.
SELECT
fruit_number,
MAX(expirationDate) as expirationDate
FROM
(SELECT
f.fruit_number,
CASE
WHEN e.expiration_date is NULL AND e.fruit_number IS NOT NULL THEN 1
ELSE 0
END AS expirationDate
FROM
expiration as e
FULL OUTER JOIN fruits as f ON f.fruit_number = e.fruit_number
WHERE
f.fruit_number IS NOT NULL
) t
GROUP BY
fruit_number
ORDER BY
fruit_number
Related
I am moving a query from SQL Server to Snowflake. Part of the query creates a pivot table. The pivot table part works fine (I have run it in isolation, and it pulls numbers I expect).
However, the following parts of the query rely on the pivot table- and those parts fail. Some of the fields return as a string-type. I believe that the problem is Snowflake is having issues converting string data to numeric data. I have tried CAST, TRY_TO_DOUBLE/NUMBER, but these just pull up 0.
I will put the code down below, and I appreciate any insight as to what I can do!
CREATE OR REPLACE TEMP TABLE ATTR_PIVOT_MONTHLY_RATES AS (
SELECT
Market,
Coverage_Mo,
ZEROIFNULL(TRY_TO_DOUBLE('Starting Membership')) AS Starting_Membership,
ZEROIFNULL(TRY_TO_DOUBLE('Member Adds')) AS Member_Adds,
ZEROIFNULL(TRY_TO_DOUBLE('Member Attrition')) AS Member_Attrition,
((ZEROIFNULL(CAST('Starting Membership' AS FLOAT))
+ ZEROIFNULL(CAST('Member Adds' AS FLOAT))
+ ZEROIFNULL(CAST('Member Attrition' AS FLOAT)))-ZEROIFNULL(CAST('Starting Membership' AS FLOAT)))
/ZEROIFNULL(CAST('Starting Membership' AS FLOAT)) AS "% Change"
FROM
(SELECT * FROM ATTR_PIVOT
WHERE 'Starting Membership' IS NOT NULL) PT)
I realize this is a VERY big question with a lot of moving parts... So my main question is: How can I successfully change the data type to numeric value, so that hopefully the formulas work in the second half of the query?
Thank you so much for reading through it all!
EDITED FOR SHORTENING THE QUERY WITH UNNEEDED SYNTAX
CAST(), TRY_TO_DOUBLE(), TRY_TO_NUMBER(). I have also put the fields (Starting Membership, Member Adds) in single and double quotation marks.
Unless you are quoting your field names in this post just to highlight them for some reason, the way you've written this query would indicate that you are trying to cast a string value to a number.
For example:
ZEROIFNULL(TRY_TO_DOUBLE('Starting Membership'))
This is simply trying to cast a string literal value of Starting Membership to a double. This will always be NULL. And then your ZEROIFNULL() function is turning your NULL into a 0 (zero).
Without seeing the rest of your query that defines the column names, I can't provide you with a correction, but try using field names, not quoted string values, in your query and see if that gives you what you need.
You first mistake is all your single quoted columns names are being treated as strings/text/char
example your inner select:
with ATTR_PIVOT(id, studentname) as (
select * from values
(1, 'student_a'),
(1, 'student_b'),
(1, 'student_c'),
(2, 'student_z'),
(2, 'student_a')
)
SELECT *
FROM ATTR_PIVOT
WHERE 'Starting Membership' IS NOT NULL
there is no "starting membership" column and we get all the rows..
ID
STUDENTNAME
1
student_a
1
student_b
1
student_c
2
student_z
2
student_a
So you need to change 'Starting Membership' -> "Starting Membership" etc,etc,etc
As Mike mentioned, the 0 results is because the TRY_TO_DOUBLE always fails, and thus the null is always turned to zero.
now, with real "string" values, in real named columns:
with ATTR_PIVOT(Market, Coverage_Mo, "Starting Membership", "Member Adds", "Member Attrition") as (
select * from values
(1, 10 ,'student_a', '23', '150' )
)
SELECT
Market,
Coverage_Mo,
ZEROIFNULL(TRY_TO_DOUBLE("Starting Membership")) AS Starting_Membership,
ZEROIFNULL(TRY_TO_DOUBLE("Member Adds")) AS Member_Adds,
ZEROIFNULL(TRY_TO_DOUBLE("Member Attrition")) AS Member_Attrition
FROM ATTR_PIVOT
WHERE "Starting Membership" IS NOT NULL
we get what we would expect:
MARKET
COVERAGE_MO
STARTING_MEMBERSHIP
MEMBER_ADDS
MEMBER_ATTRITION
1
10
0
23
150
I need help with a SQL query to check if a numeric column contains a number in ascending or descending order.
eg. 123456 or 654321
This is to avoid people entering some random values in a customer phone number column, users are required to give valid phone number input.
I want to achieve this without using a function.
UPDATE: #LukStorms had kindly answered my question. Many thanks. Thanks to others who looked at my question and left comments. However I would really appreciate if the comment helps solve the problem. My scenario is different, I cannot post the entire use case here. The ask is I must validate the column in the same way.
To check if it's like a sequence of digits?
Then you can simply use LIKE
select num
, cast(case
when '1234567890123456789' like concat('%',num,'%')
then 1
when '9876543210987654321' like concat('%',num,'%')
then 1
else 0 end as bit) as isSequence
from (values
(123456),
(765432),
(797204)
) nums(num)
num
isSequence
123456
True
765432
True
797204
False
Or use CHARINDEX
select num
, cast(case
when 0 < charindex(concat(num,''),'1234567890123456789') then 1
when 0 < charindex(concat(num,''),'9876543210987654321') then 1
else 0 end as bit) as isSequence
from (values
(123456),
(765432),
(797204)
) nums(num)
Demo on db<>fiddle here
I know what this warning means, however in this case there are definitely no null values.
The result also appears to be correct, but the warning makes me curious (and concerned) since it means there's something in play that I don't understand.
The warning is:
Warning: Null value is eliminated by an aggregate or other SET operation.
Here's the statement:
UPDATE Contacts
SET IsActiveCampaignClient = 1,
NeedsActiveCampaignSync = 1
FROM (
SELECT dbo.Contacts.ID
FROM dbo.Contacts
LEFT OUTER JOIN dbo.Order_Batches ON dbo.Order_Batches.EnteredByContactID = dbo.Contacts.ID
GROUP BY dbo.Contacts.ID
HAVING (COUNT(dbo.Order_Batches.ID) > 0)
) i
WHERE i.ID = Contacts.ID
As you can see, this is an UPDATE statement where I needed to do some join logic, and the COUNT() statement must be the problem. But if I take that nested SELECT out and run it by itself, there are no nulls in the result:
ID
37
39
52
54
79
81
I assume there's something about how this nested select works that I don't understand. I've tried looking at execution plans and pulling this apart in various ways to reveal a null value or some other problem. I've tried making tweaks to the statement to try and get a null to appear - no luck.
So, to be clear, I would like to understand why this message occurs, but only when the query is nested inside an UPDATE statement's FROM clause.
Does not need aggregation if you are ensuring that there is at least an order by the contact to update this. Use EXISTS instead.
UPDATE c
SET IsActiveCampaignClient = 1,
NeedsActiveCampaignSync = 1
FROM Contacts c
WHERE exists (
(
SELECT 1 -- making sure there is at least an order
FROM Order_Batches o
where o.EnteredByContactID = c.ID
)
I understand why null + 1 or (1 + null) returns null: null means "unknown value", and if a value is unknown, its successor is unknown as well. The same is true for most other operations involving null.[*]
However, I don't understand why the following happens:
SELECT SUM(someNotNullableIntegerField) FROM someTable WHERE 1=0
This query returns null. Why? There are no unknown values involved here! The WHERE clause returns zero records, and the sum of an empty set of values is 0.[**] Note that the set is not unknown, it is known to be empty.
I know that I can work around this behaviour by using ISNULL or COALESCE, but I'm trying to understand why this behaviour, which appears counter-intuitive to me, was chosen.
Any insights as to why this makes sense?
[*] with some notable exceptions such as null OR true, where obviously true is the right result since the unknown value simply does not matter.
[**] just like the product of an empty set of values is 1. Mathematically speaking, if I were to extend $(Z, +)$ to $(Z union {null}, +)$, the obvious choice for the identity element would still be 0, not null, since x + 0 = x but x + null = null.
The ANSI-SQL-Standard defines the result of the SUM of an empty set as NULL. Why they did this, I cannot tell, but at least the behavior should be consistent across all database engines.
Reference: http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt on page 126:
b) If AVG, MAX, MIN, or SUM is specified, then
Case:
i) If TXA is empty, then the result is the null value.
TXA is the operative resultset from the selected column.
When you mean empty table you mean a table with only NULL values, That's why we will get NULL as output for aggregate functions. You can consider this as by design for SQL Server.
Example 1
CREATE TABLE testSUMNulls
(
ID TINYINT
)
GO
INSERT INTO testSUMNulls (ID) VALUES (NULL),(NULL),(NULL),(NULL)
SELECT SUM(ID) FROM testSUMNulls
Example 2
CREATE TABLE testSumEmptyTable
(
ID TINYINT
)
GO
SELECT SUM(ID) Sums FROM testSumEmptyTable
In both the examples you will NULL as output..
If not, is there an alternate way to switch through SELECT statements using a CASE or IF/THEN identifier WITHOUT putting the statement in a scalar variable first?
Is there a way to format this without using IS and using an = sign for it to work?
SELECT ID FROM TABLE WHERE ID = Null
No. NULL isn't a value. Think of NULL as a condition, with IS NULL or IS NOT NULL is testing for this condition.
In this example you can test for the actual value, or lack of value represented by a conditon
WHERE
(X IS NULL OR X = #X)
OR
WHERE
(#X IS NULL OR X = #X)
Or test for your definite conditions first:
WHERE
CASE X
WHEN 1 THEN
WHEN 2 THEN
ELSE -- includes NULL
END = ...
Your question is abstract so hard to give a more precise answer.
For example, are you having problems with NOT IN and NULL? If so, use NOT EXISTS.