conditional insert into mysql - mysql

I am quite newbie with MySQL (5.1) and I don't achieve to do a conditional "insert into".
For each record, I want to insert into the same columns (1 and 2) from an empty/destination table, either 2 fields (A and B) or 2 other fields (C and D) from a source table containing several records.
Here my query:
INSERT INTO DB.table_destination(field1, field2)
SELECT
CASE
WHEN fieldAA='value1' THEN (
SELECT fieldA, fieldB
FROM DB.table_source<BR>
)
ELSE (
SELECT fieldC, fieldD
FROM DB.table_source
)
END
FROM db.table_source
Note that the fieldAA belongs to the table_source too.
I have an error around the second SELECT. Depending on some tiny changes in my script, it sometimes complains that I have more than one row.
I am stuck on that issue for a while, so I will greatly appreciate your help.
[EDIT]
Thanks a lot for your advices! It works perfectly with this simple example.
However, my study case is in the real life a bit more complex, as I have to deal with 3 source tables, including one condition (JOIN) between tables_source_1 and table_source_2, and one spatial function between table_source_1 and table_source_3.
Here my query that returns me the result from only one condition:
INSERT INTO test.OBSERVATION (CODE_INSEE,ID_SITE,LONGWGS84,LATWGS84)
SELECT
CASE METHODE_LOC WHEN '13' THEN insee_zerofill ELSE INSEE_zero END,
CASE METHODE_LOC WHEN '13' THEN '' ELSE ID_SITE END,
CASE METHODE_LOC WHEN '13' THEN GPS_TEL_LNG ELSE LONG_LIEU_DIT END,
CASE METHODE_LOC WHEN '13' THEN GPS_TEL_LAT ELSE LAT_LIEU_DIT END
FROM odk.test_insee, odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.GISWithin(GeomFromText(CONCAT('POINT(',GPS_TEL_LNG,' ',GPS_TEL_LAT,')')), SHAPE)
Tables details
1) odk.test_insee contains SHAPE (geometry used in the spatial function GISWithin) and insee_zerofill.
2) DEMO_OISEAUX9_FULL_CORE contains GPS_TEL_LNG & GPS_TEL_LAT (filled when METHODE_LOC is equal to 13), ID_SITE (filled when METHODE_LOC is different from 13).
3) odk.site_clone contains INSEE_zero, LONG_LIEU_DIT, LAT_LIEU_DIT.
I tried to set a CASE in the WHERE condition to tell it to perform the function only when ID_SITE is null, but without success so far.
Any ideas?
Thanks in advance!
[EDIT 2]
Now, it works! I should have repeated the specific condition within the CASE for EACH field to select, as followed:
SELECT
CASE METHODE_LOC WHEN '13' THEN
(SELECT insee_zerofill
FROM odk.test_insee, odk.DEMO_OISEAUX9_FULL_CORE
WHERE odk.GISWithin(GeomFromText(CONCAT('POINT(',`GPS_TEL_LNG`,' ',`GPS_TEL_LAT`,')')), SHAPE) )
ELSE
(SELECT INSEE_zero
FROM odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE
ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS is not NULL )
END,
CASE METHODE_LOC WHEN '13' THEN ''
ELSE
(SELECT ID_SITE
FROM odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE
ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS is not NULL )
END,
CASE METHODE_LOC WHEN '13' THEN
(SELECT GPS_TEL_LNG
FROM odk.test_insee, odk.DEMO_OISEAUX9_FULL_CORE
WHERE odk.GISWithin(GeomFromText(CONCAT('POINT(',`GPS_TEL_LNG`,' ',`GPS_TEL_LAT`,')')), SHAPE) )
ELSE
(SELECT LONG_LIEU_DIT
FROM odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE
ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS is not NULL )
END,
CASE METHODE_LOC WHEN '13' THEN
(SELECT GPS_TEL_LAT
FROM odk.test_insee, odk.DEMO_OISEAUX9_FULL_CORE
WHERE odk.GISWithin(GeomFromText(CONCAT('POINT(',`GPS_TEL_LNG`,' ',`GPS_TEL_LAT`,')')), SHAPE) )
ELSE
(SELECT LAT_LIEU_DIT
FROM odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE
ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS is not NULL )
END
FROM odk.DEMO_OISEAUX9_FULL_CORE ;

this wawy for case
INSERT INTO DB.table_destination(field1, field2)
SELECT CASE fieldAA WHEN 'value1' THEN fieldA ELSE fieldC END ,
CASE fieldAA WHEN 'value1' THEN fieldB ELSE fieldD END
FROM db.table_source
If i understand correctly you question and you want perform your insert select only if ID_SITE is null then you should use
INSERT INTO test.OBSERVATION (CODE_INSEE,ID_SITE,LONGWGS84,LATWGS84)
SELECT
CASE METHODE_LOC WHEN '13' THEN insee_zerofill ELSE INSEE_zero END,
CASE METHODE_LOC WHEN '13' THEN '' ELSE ID_SITE END,
CASE METHODE_LOC WHEN '13' THEN GPS_TEL_LNG ELSE LONG_LIEU_DIT END,
CASE METHODE_LOC WHEN '13' THEN GPS_TEL_LAT ELSE LAT_LIEU_DIT END
FROM odk.test_insee, odk.site_clone RIGHT JOIN odk.DEMO_OISEAUX9_FULL_CORE ON odk.site_clone.ID_SITE=odk.DEMO_OISEAUX9_FULL_CORE.SITE_OBS
WHERE odk.GISWithin(GeomFromText(CONCAT('POINT(',GPS_TEL_LNG,' ',GPS_TEL_LAT,')')), SHAPE)
AND ID_SITE is null ;
you can use both case when is null
INSERT INTO DB.table_destination(field1, field2)
SELECT CASE fieldAA WHEN is null THEN fieldA ELSE fieldC END ,
CASE fieldAA WHEN 'value1' THEN fieldB ELSE fieldD END
FROM db.table_source
or ifnull
INSERT INTO DB.table_destination(field1, field2)
SELECT ifnull( fieldAA, your_column_for_null) ,
CASE fieldAA WHEN 'value1' THEN fieldB ELSE fieldD END
FROM db.table_source

Related

How to handle null and NULL value in sql

So I have been facing this weird situation in mysql where somehow null values are inserted in my table.
I'm talking about null value not NULL value.
I have attached image for better understating
as you can see name column have null and mobile_no have NULL
So after using this query
select Case when t1.name IS NULL then 'NA'
when t1.name= 'NA' or 'null' or NULL then 'NA'
else t1.name end as 'Name',
Case when t1.mobile_no IS NULL then 'NA'
when t1.mobile_no= 'NA' or 'null' or NULL then 'NA'
else t1.mobile_noend as 'Mobile no' from student;
after this I'm getting this result
|Name|Mobile no|
----------------
|null|NA |
but I want below result
|Name|Mobile no|
----------------
|NA |NA |
To compare a column with multiple values use col IN (x, y, z), not col = x OR y OR z.
You also can't compare with NULL using = or IN, so that has to be a separate check.
select
Case
when t1.name IS NULL OR t1.name IN ('NA' or 'null') then 'NA'
else t1.name
end as 'Name'
Can you try use IN statement? That should work.
select Case WHEN (t1.name IN ('NA', 'null') OR t1.name IS NULL) THEN 'NA' else t1.name end as 'Name',
Case WHEN (t1.mobile IN ('NA', 'null') OR t1.mobile IS NULL) THEN 'NA' else t1.mobile_no end as 'Mobile no' from student;

MySQL : using sum in( case when ) statement shows 0 as result

new to MySQL..so pls help me out with this basic code..
i have a query something like this...
select weekofyear(id_time),
(id),
#Tat1:=exp1,
#Tat2:=exp2,
#check1:=exp3,
#check2:=exp4,
(case when #check2=0 then
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+10))) then 1 else 0 end)
else
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+20))) then 1 else 0 end)
end) as BO
from datb
where cid=18
and id_time between '2019-11-01 06:00:00' and '2019-11-25 06:00:00'
and it gives correct results as--here
however i want to use sum after case when statement so that I can get total values where BO=1 and group by week of year , so i made following changes-
select weekofyear(id_time),
count(id),
#Tat1:=exp1,
#Tat2:=exp2,
#check1:=exp3,
#check2:=exp4,
sum(case when #check2=0 then
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+10))) then 1 else 0 end)
else
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+20))) then 1 else 0 end)
end) as BO
from datb
where cid=18
and id_time between '2019-11-01 06:00:00' and '2019-11-25 06:00:00'
group by weekofyear(id_time)
but it always returns 0 as output.
Output --here 2
Please help , I don't know what am I doing wrong here.
Thanx !
As others have already said, session variables can be unpredictable (especially when aggregation gets mixed in). That said, it doesn't look like you're using the session variables to carry over values from one row to the next (as is often done), but to just make aliases of sorts for calculations you don't want to repeat.
A better way to handle that is just through subqueries.
SELECT woy, id, Tat1, Tat2, check1, check2
, CASE
WHEN check2=0 THEN (
CASE
WHEN (Tat1>(Tat2+30) OR (check1=1 AND (Tat1>Tat2+10))) THEN 1
ELSE 0
END
)
ELSE (
CASE WHEN (Tat1>(Tat2+30) OR (check1=1 AND (Tat1>Tat2+20))) THEN 1
ELSE 0
END
)
END AS BO
FROM (
SELECT WEEKOFYEAR(id_time) AS woy
, id
, exp1 AS Tat1
, exp2 AS Tat2
, exp3 AS check1
, exp4 AS check2
FROM datb
WHERE cid=18
AND id_time BETWEEN '2019-11-01 06:00:00' AND '2019-11-25 06:00:00'
) AS subQ
;
You can then tweak the above query for aggregation, or use it as a subquery for an aggregating outer query.

How to use Group By correclty?

I have this query that worked fine:
select isnull(email,'') as Email ,isnull([ERPM First Name],'')+' '+isnull([ERPM Last Name],'')[User Name],
geo,CustomerID,BusinessID,courseid, MIN (CompletionDate) [1st Training Course],
CASE WHEN COURSEID IN (37445,37644,37443,37778,37435,37733,37584,37483,37392,37817,
37259,37597,37391,37393,37792,37816,37256,37257,37258,37484,37485,37486)
THEN 'Yes' ELSE 'No'
END AS [Is it a campaing course?],
CASE WHEN CompletionDate BETWEEN '2017-03-10' AND '2017-09-03' THEN 'Yes' ELSE 'No'
END AS [During Campaign],
CASE WHEN COURSEID IN (37256,37257,37258,37484,37485,37486) AND
CompletionDate BETWEEN '2017-03-10' AND '2017-09-03' THEN 'ON Period Bonus' ELSE '-'
END AS [1st BONUS]
from vw_Training_Cube
where [Is disti or subdisti?] = 'No' and [Is test account?] = 'No'
and Email<>'0'
GROUP BY isnull(email,''),isnull([ERPM First Name],'')+' '+isnull([ERPM Last Name],''),geo,CustomerID,BusinessID,courseid,
CASE WHEN COURSEID IN (37445,37644,37443,37778,37435,37733,37584,37483,37392,
37817,37259,37597,37391,37393,37792,37816,37256,37257,37258,37484,37485,37486)
THEN 'Yes' ELSE 'No'
END,
CASE WHEN CompletionDate BETWEEN '2017-03-10' AND '2017-09-03' THEN 'Yes' ELSE 'No'
END,
CASE WHEN COURSEID IN (37256,37257,37258,37484,37485,37486) AND
CompletionDate BETWEEN '2017-03-10' AND '2017-09-03' THEN 'ON Period Bonus' ELSE '-5'
END
but now instead of grouping by email, I want to group by business id. But simply swapping the order doesnt solve the problem.
Unless you need an aggregate function such as COUNT() MIN() or MAX() then you can simplify your query by using select distinct.
SELECT DISTINCT
ISNULL(email, '')
AS Email
, ISNULL([ERPM First Name], '') + ' ' + ISNULL([ERPM Last Name], '')
[User Name]
, geo
, CustomerID
, BusinessID
, courseid
, MIN(CompletionDate) [1st Training Course]
, CASE
WHEN COURSEID IN (37445, 37644, 37443, 37778, 37435, 37733, 37584, 37483, 37392, 37817,
37259, 37597, 37391, 37393, 37792, 37816, 37256, 37257, 37258, 37484, 37485, 37486) THEN
'Yes'
ELSE
'No'
END AS [Is it a campaing course?]
, CASE
WHEN CompletionDate BETWEEN '2017-03-10' AND '2017-09-03' THEN
'Yes'
ELSE
'No'
END AS [During Campaign]
, CASE
WHEN COURSEID IN (37256, 37257, 37258, 37484, 37485, 37486) AND
CompletionDate BETWEEN '2017-03-10' AND '2017-09-03' THEN
'ON Period Bonus'
ELSE
'-'
END AS [1st BONUS]
FROM vw_Training_Cube
WHERE [Is disti or subdisti?] = 'No'
AND [Is test account?] = 'No'
AND Email <> '0'
ORDER BY BusinessID
To reduce the rows further, you also need to remove columns - OR - start using aggregate functions. e.g. the following would produce the minimum set of rows to list every BusinessID that meets the where conditions.
SELECT DISTINCT
BusinessID
FROM vw_Training_Cube
WHERE [Is disti or subdisti?] = 'No'
AND [Is test account?] = 'No'
AND Email <> '0'
ORDER BY BusinessID
;
Keep adding columns to that to see the effect on number of rows.

Sum of 2 fetched columns in other column in Big query SQL

select x,
count(case when i='abc' then 1 else null end) as ele1,
count(case when i='def' then 1 else null end) as ele2,
sum(ele1+ele2) as sum1 from (INNER QUERY)
When i am using sum(ele1+ele2), it is throwing error that ele1 not found. How to fetch sum1 in the same query without using any other outer query?
You can't use alias as column name in select
select x,
count(case when i='abc' then 1 else null end) as ele1,
count(case when i='def' then 1 else null end) as ele2,
sum( ( case when i='abc' then 1 else null end ) +
( case when i='def' then 1 else null end ) ) as sum1
from (INNER QUERY)
You cannot use alias as a column name, but if your concern is in verboseness - in your particular case you can write something like below, which is easy readable and skinny enough (for BigQuery Legacy SQL)
SELECT
SUM( i ='abc' ) AS ele1,
SUM( i = 'def' ) AS ele2,
SUM( i IN ('abc', 'def') ) AS sum1
FROM (INNER QUERY)

INT comparison without WHERE [duplicate]

This question already has answers here:
INT comparison without WHERE statement
(4 answers)
Closed 9 years ago.
Thread moved to: INT comparison without WHERE statement
Minor point, you have at least three syntax errors in your query. There is the comma after Day 0, the lack of a date part in datediff(), and the double equal sign. As to what you are trying to accomplish, it a case construct might be the way to go.
select case
when datediff(day, date1, date2) = 0 then 'Day 0'
when abs(datediff(day, date1, date2)) = 1 then 'Day 1'
else 'something else' end WhatDay
from etc
You probably want a where clause so that you are not querying the entire table. Doing that is rarely necessary.
If you need multiple columns then you only have one realistic choice, a CASE statement, but that's messy. However, with a little joining we can make it cleaner. Let's assume the key for the table is Id, we might write a statement like this:
SELECT t.*,
CASE WHEN i.diff = 0 THEN 'Day 0' ELSE NULL END AS Day0,
CASE WHEN i.diff = 1 THEN 'Day 1' ELSE NULL END AS Day1,
CASE WHEN i.diff = 2 THEN 'Day 2' ELSE NULL END AS Day2,
CASE WHEN i.diff = 3 THEN 'Day 3' ELSE NULL END AS Day3,
CASE WHEN i.diff = 4 THEN 'Day 4' ELSE NULL END AS Day4,
CASE WHEN i.diff = 5 THEN 'Day 5' ELSE NULL END AS Day5,
FROM table t
JOIN (
SELECT Id, DATEDIFF(
STR_TO_DATE(date, '%Y-%m-%d %H:%i:%s'), b.datetwo
) AS diff
FROM table
) i ON i.Id = t.Id AND i.diff >= 0 AND i.diff <= 5
With this statement we now know what bucket each row falls into; if the value isn't NULL.