I am passing result of FULL Outer join to Conditional Split and Filtering Records on the basis of following rules . Basically both tables has same schema and Primarykey values are same.
a. If Primary key of Source is NULL
b. If Primary Key of Destination is NULL
c. If Source and Destination key matches.
It works fine for (a) and (b) but fails for (c)
Source.Id == Destination.Id
and throws exception that condition evaluated as NULL where Boolean was expected. How i can make this work?
Conditional Split gets input from Merge Join and it's a FULL OUTER JOIN as i need FULL OUTER join results here
Your third condition should start with a ISNULL check again before you compare your values. Like the following:
!ISNULL(Source.Id) && !ISNULL(Destination.Id) && Source.Id == Destination.Id
You need to handle every column that can be NULL in your condition.
Since you are comparing Id's, another option would be:
(ISNULL(Source.Id) ? 0 : Source.Id) == (ISNULL(Destination.Id) ? 0 : Destination.Id)
If comparing strings, you can replace the zeroes with blank spaces.
Alternatively you can use the following syntax:
REPLACENULL(Source.Id,0) == REPLACENULL(Destination.Id,0)
Related
I have a query where i have "TEST"."TABLE" LEFT JOINED to PUBLIC."SchemaKey". Now in my final select statement i have a case statement where i check if c."Type" = 'FOREIGN' then i want to grab a value from another table but the table name value i am using in that select statement is coming from the left joined table column value. I've tried multiple ways to get to work but i keep getting an error, although if i hard code the table name it seems to work. i need the table name to come from c."FullParentTableName". Is what i am trying to achieve possible in snowflake and is there a way to make this work ? any help would be appreciated !
SELECT
c."ParentColumn",
c."FullParentTableName",
a."new_value",
a."column_name"
CASE WHEN c."Type" = 'FOREIGN' THEN (SELECT "Name" FROM TABLE(c."FullParentTableName") WHERE "Id" = 'SOME_ID') ELSE null END "TestColumn" -- Need assistance on this line...
FROM "TEST"."TABLE" a
LEFT JOIN (
select s."Type", s."ParentSchema", s."ParentTable", s."ParentColumn", concat(s."ParentSchema",'.','"',s."ParentTable",'"') "FullParentTableName",s."ChildSchema", s."ChildTable", trim(s."ChildColumn",'"') "ChildColumn"
from PUBLIC."SchemaKey" as s
where s."Type" = 'FOREIGN'
and s."ChildTable" = 'SOMETABLENAME'
and "ChildSchema" = 'SOMESCHEMANAME'
) c
on a."column_name" = c."ChildColumn"
Thanks !
In Snowflake you cannot dynamically use the partial results as tables.
You can use a single bound value via identifier to bind a value to table name
But you could write a Snowflake Scripting but it would need to explicitly join the N tables. Thus if you N is fixed, you should just join those.
I have an SQL statement with a WHERE clause where I am adding additional filters if a variable passed into the stored procedure IN parameter is a certain value.
The IN parameter is called filterID and can be empty if I need all records, or have the value SEN,EAL or MAGT if I want to only select the records which have IDs in those columns from the LEFT JOINED tables.
This is the extract from the SQL query to show the joining of the tables and the additional filter.
LEFT JOIN tbl_sen ON tbl_pupil.pupilID = tbl_sen.pupilID
LEFT JOIN tbl_eal ON tbl_pupil.pupilID = tbl_eal.pupilID
LEFT JOIN tbl_magt ON tbl_pupil.pupilID = tbl_magt.pupilID
WHERE
tbl_test.schoolID=schoolID
AND (
(filterID='SEN' AND tbl_sen.senID IS NOT NULL) OR
(filterID='EAL' AND tbl_eal.ealID IS NOT NULL) OR
(filterID='MAGT' AND tbl_magt.magtID IS NOT NULL))
AND tbl_test.import=1;
WHen I execute the stored procedure with the values, it shows the correct results. However, if I don't want to add the filter and pass filterID as empty/NULL, it returns 0 results when I need it to return ALL the results.
Can anyone spot what I'm doing wrong?
...
AND CASE filterID WHEN 'SEN' THEN tbl_sen.senID IS NOT NULL
WHEN 'EAL' THEN tbl_eal.ealID IS NOT NULL
WHEN 'MAGT' THEN tbl_magt.magtID IS NOT NULL
ELSE filterID IS NULL END
AND ...
As I understand the filterID is local variable (SP parameter) so there is no problem to use it twice (rather than bound parameter of the query - in this case you may use user-defined intermediate variable).
Simplified DEMO
AND (
(filterID='SEN' AND tbl_sen.senID IS NOT NULL) OR
(filterID='EAL' AND tbl_eal.ealID IS NOT NULL) OR
(filterID='MAGT' AND tbl_magt.magtID IS NOT NULL) OR
(filterID IS NULL)
)
I have four tables for a form-builder in my databse.
fields (fieldID(PK), typeID, fieldName, ...) - This table is a row by row list of all fields to be in the form
fields_types (typeID(PK), htmlType, ...) - This is a table that links fields to html types (and other settings)
fields_meta (FieldMetaID(PK), FieldID, mName, mValue) - Additional settings for fields, but more specific. A textarea field might have a height attribute, but almost no other field would use that.
fields_tyeps_meta (TypeMetaID(PK), typeID, tmName, tmValue) - Defines what extraneous settings a field can have, and also supplies default values if it's not explicitly set)
So my Query currently looks something like this
SELECT *
FROM Fields F
JOIN Field_Types FT
on FT.FieldID = F.FieldID
LEFT
JOIN Field_Meta FM
on FM.FieldID = F.FieldID
I was wondering if there's a way to join Fields_Types_Meta so that when the row's JOIN to Fields_Meta doesn't return a row (no mValue), it returns tmValue
I realize I can use something like (CASE WHEN mValue = "" THEN tmValue ELSE mValue END) AS UseValue, but I might have fields where I want to allow the value to be set to empty.
Edit: I could probably do something with a subquery and COUNT, using a CASE decision based on that. It might not be the healthiest performance-wise, but this query runs and caches itself til server restart, or until it's told to run again (updates to form design)
It looks like you just want ¢oalesce():
coalesce(FM.mValue, FT.tmValue) as UseValue
When FM.mValue is null, coalesce() returns FT.tmValue instead.
If you have null values in FM that you want to preserve in the result set, then use a case expression instead:
case when FM.FieldID IS NULL THEN FT.tmValue ELSE FM.mValue END as UseValue
This phrases as: when the left join did find a match in FM, use mValue from that row (even if it is null), else use FT.tmValue.
I have problem with receiving rows if id from one table dont match second one.
If zamowienia.id_telefon is null or dont match i dont recive whole row.
I want to instead get column crm2018.telefon.numer with "0" or null value. Please help :)
I tried something like that but its obvious syntax eror:
SELECT
crm2018.zamowienia.*,
crm2018.telefon.numer
FROM
crm2018.zamowienia
JOIN crm2018.telefon
WHERE
if (zamowienia.id_telfon != "0") zamowienia.id_telefon = telefon.id_telefon else crm2018.telefon.numer as "0"
Here's working code but with missing rows.
SELECT
crm2018.zamowienia.*,
crm2018.telefon.numer
FROM
crm2018.zamowienia
JOIN crm2018.telefon
WHERE
zamowienia.id_telefon = telefon.id_telefon
Just use LEFT JOIN instead of (INNER) JOIN.
Accordingly, you need to move the join condition from the WHERE clause to the ON clause of the join, to avoid filtering out unmatched records. Please note that as it is, your query has a JOIN without ON clause : this is a syntax error in all SQL dialects.
Finally, I would recommend using table aliases in the query : this makes it easier to read and to maintain.
SELECT
z.*,
t.numer
FROM
crm2018.zamowienia AS z
LEFT JOIN crm2018.telefon AS t
ON z.id_telefon = t.id_telefon
When no record is available in crm2018.telefon for the given crm2018.zamowienia, the record will still be displayed, with all columns coming from crm2018.telefon showing NULL values.
If needed, you can turn NULL values to 0 with the COALESCE() function, like :
COALESCE(t.numer, 0)
I'm dealing with a situation at work where someone set up some tables without a primary key (arghhh). now I'm trying to compare dev data to prod data and the best I can tell is that theres a slight difference in the number of rows.
I figured the best way I could compare data is to do a join on every column, but I'm getting unexpected results.
to test this out I just joined the same table to itself. This table has 1309 rows.. but when I join on every column i get 1014. Thats less rows. If anything i'd expect to get more. What gives?
select *
from `default_tire_classifications` tc1
join `default_tire_classifications` tc2
on tc1.`marketing_tread_name` = tc2.`marketing_tread_name`
AND tc1.`size` = tc2.`size`
AND tc1.product_category = tc2.product_category
AND tc1.application = tc2.application
AND tc1.vehicle_type = tc2.vehicle_type
AND tc1.oem_part = tc2.oem_part
AND tc1.position = tc2.position
AND tc1.size = tc2.size
AND tc1.sect_wdth = tc2.sect_wdth
AND tc1.aspect_ratio = tc2.aspect_ratio
AND tc1.rim_size = tc2.rim_size
AND tc1.speed_rating = tc2.speed_rating
AND tc1.load_index = tc2.load_index
I suspect some of the columns contain NULL values. An equality comparison to a NULL value yields NULL. (SQL tri-valued Boolean logic.)
To do a comparison that yields TRUE when both sides are NULL, you could do something like this
( tc1.col = tc2.col OR ( tc1.col IS NULL AND tc2.col IS NULL ) )
MySQL also provides a non-standard "null-safe" equality comparison operator <=> (spaceship) that does the same thing.
tc1.col <=> tc2.col
returns either TRUE or FALSE, and will return TRUE when the values on both sides are NULL.
So, replacing the = (equality comparison) operator with <=> operator should resolve the problem with comparing NULL values.
(This isn't to say that NULL values is a problem, or is the only problem.)
If your fields contains NULL, you will lost them. Because NULL = NULL is not true.