MySQL Case in Update - mysql

I've browsed the forums. I've tested several different methods. I just can't get this to work.
GOAL:
Update the next column if an answer exists in the previous column
Q1 IS NULL at this point and I want it set to 1
Q2 IS NULL and I want it to stay NULL if Q1 IS NULL, If Q1 has an answer, update this column to 1
PROBLEM:
Both columns always update to 1
ATTEMPTS:
UPDATE Story1_Responses
SET Q1 = IFNULL(Q1,'1'),
Q2 = CASE WHEN Q1 IS NULL THEN NULL ELSE '1' END
WHERE UserID = 16
UPDATE Story1_Responses
SET Q1 = IFNULL(Q1,'1'),
Q2 = CASE WHEN IFNULL(Q1,'') = '' THEN NULL ELSE '1' END
WHERE UserID = 16
UPDATE Story1_Responses
SET Q1 = IFNULL(Q1,'1'),
Q2 = CASE WHEN COALESCE(Q1, '') = '' THEN NULL ELSE '1' END
WHERE UserID = 16
UPDATE Story1_Responses
SET Q1 = IFNULL(Q1,'1'),
Q2 = CASE WHEN Q1 IS NOT NULL THEN '1' ELSE IFNULL(Q2,NULL) END
WHERE UserID = 16
THOUGHTS:
It seems to me that MySQL updates the first column prior to the second column being evaluated even though they are in the same update statement execution.

Order is important. First set Q2 (because it checks the previous value of Q1), then set Q1.
UPDATE Story1_Responses
SET Q2 = CASE WHEN Q1 IS NULL THEN NULL ELSE '1' END,
Q1 = IFNULL(Q1,'1')
WHERE UserID = 16;
SQLFiddle

Related

MySql select statement with conditional where clause

I am trying to write a MySql statement with a conditional where clause.
something like this:
set #price = 5000 ;
set #city = 1324368075;
select count(*)
from property
where case when #price is not null then
price < #price
end
and (case when #city is not null then
CityId = #city
end)
the variable should be included in the query only if it is not null.
My attempts have failed so far. Any ideas?
Edited:
Sorry I spoke too soon ysth,
these two queries are supposed to yield the same count but they dont.
Edit #2: Execution plan & indexes
Here's the query:
set #CountryId = null ;
set #CityId = 1324368075 ;
set #StateProvince = null ;
set #CategoryId = null ;
set #TransactionTypeId = null;
set #Price = 5000;
SELECT
Count(*)
FROM
meerkat.property
WHERE
(CASE WHEN #CountryId IS NOT NULL THEN CountryId = #CountryId ELSE 1 END)
AND (CASE WHEN #CityId IS NOT NULL THEN CityId = #CityId ELSE 1 END)
AND (CASE WHEN #CategoryId IS NOT NULL THEN CategoryId = #CategoryId ELSE 1 END)
AND (CASE WHEN #StateProvince IS NOT NULL THEN StateProvince = #StateProvince ELSE 1 END)
AND (CASE WHEN #TransactionTypeId IS NOT NULL THEN TransactionTypeId = #TransactionTypeId ELSE 1 END)
AND (CASE WHEN #Price IS NOT NULL THEN Price <= #Price ELSE 1 END)
AND IsPublic = 1
AND IsBlocked = 0;
Thanks in advance
If no when conditions are met, case returns null. If you want each test to pass, you need to return a true value instead, so:
case when #price is not null then
price < #price
else 1 end
and ...

if statement mySQL

I am trying to figure out how to do an if statement that will essentially calculate the stock of an item based on the dates in the tp_rental table.
I was hoping to do something like :
if Date_Due has an entry but Date_Returned does not
then set stock -1
if Date_Due has an entry and Date_returned has an entry entered
then set stock +1
See below for my attempt, not sure if i need a join here?
update title_platform
set Stock = case
when tp_rental.Date_Returned is not null then stock -1
else stock +1
end
Am I going about this the right way?
You need an UPDATE statement with a join between the 2 tables and a CASE expression:
update title_platform p inner join tp_rental r
on r.platformid = p.platformid
set p.stock = p.stock + case
when r.date_due is not null and r.date_returned is null then -1
when r.date_due is not null and r.date_returned is not null then 1
else ? -- if there is another option
end
Remove the else part if it is not needed.
Edit: if there are multiple rows in tp_rental for each platformid then you must aggregate first and then join:
update title_platform p inner join (
select platformid,
sum(date_due is not null and date_returned is not null) -
sum(date_due is not null and date_returned is null) result
from tp_rental
group by platformid
) r on r.platformid = p.platformid
set p.stock = case
when p.stock + r.result < 0 then 0
else p.stock + r.result
end

If I query a record that doesn't exist then I will get nothing returned. I'd prefer that 0 is returned in that scenario

Here's my simple query. If I query a record that doesn't exist then I will get nothing returned. I'd prefer that 0 is returned in that scenario.
Please help me out from this.Thanks in advance
Here's my simple query. If I query a record that doesn't exist then I will get nothing returned. I'd prefer that 0 is returned in that scenario.
Please help me out from this.Thanks in advance
SELECT *
FROM (
SELECT DISTINCT emp.EMP_CODE
,emp.EMP_NAME
,ROW_NUMBER() OVER (
PARTITION BY emp.emp_code ORDER BY emp.EFFECTIVE_FROM DESC
) AS Row
,CASE
WHEN et.DAY = 03
AND et.MONTH = 02
AND et.YEAR = 16
AND et.EMP_CODE = emp.EMP_CODE
AND et.site_id = 21
THEN et.GENERAL_SHIFT
ELSE '0'
END AS G
,CASE
WHEN et.DAY = 03
AND et.MONTH = 02
AND et.YEAR = 16
AND et.EMP_CODE = emp.EMP_CODE
AND et.site_id = 21
THEN et.FIRST_SHIFT
ELSE '0'
END AS F
,CASE
WHEN et.DAY = 03
AND et.MONTH = 02
AND et.YEAR = 16
AND et.EMP_CODE = emp.EMP_CODE
AND et.site_id = 21
THEN et.SECOND_SHIFT
ELSE '0'
END AS S
,CASE
WHEN et.DAY = 03
AND et.MONTH = 02
AND et.YEAR = 16
AND et.EMP_CODE = emp.EMP_CODE
AND et.site_id = 21
THEN et.THIRD_SHIFT
ELSE '0'
END AS T
FROM dbo.EMP_FPONM_EMPLOYEE_INFORMATION emp
LEFT JOIN dbo.EMP_FPONM_EMP_TIME_SHEET et ON emp.EMP_CODE = et.EMP_CODE
WHERE EMP.SITE_ID = 21
AND emp.DEPT_NAME = #DEPT_NAME
AND emp.STATUS = 'Present'
AND et.DAY = 03
AND et.MONTH = 02
AND et.YEAR = 16
) a
WHERE a.Row = 1
You can probably use ISNULL operator for this task.
What ISNULL allows you to do is to check if a particular value in a SQL operation is NULL and allows you to return any custom value in it's place. The non-NULL values are unaffected. It works something like this:
SELECT Name, ISNULL(Department, 'Unassigned')
FROM [dbo].[Employee]
What this does is, for any employee who has a NULL field in the department column, the output table shows the Department column value as Unassigned.
You can also use the entire SQL query as an input too.
SELECT ISNULL( (SELECT MAX(Score) FROM [dbo].[Students]), 'Unchecked')
In this case if the max score from the student table is NULL we receive the output as Unchecked.
You can find detailed documentation here.
Hope this helps.

Mysql return null if subquery returns null

Hy guys, sometimes my subquery return null which is ok, it should return null, but in those cases i would like my "parent select" to return null.
Is that possible?
And if yes, then how?
Heres the code:
SELECT
`company`.`companyID`,
`company`.`companyName`,
`company`.`companyName`,
`company`.`companyEmail`,
`company`.`contactEmail`,
`company`.`companyTel`,
(
SELECT
`package_map`.`szekhely_endDate`
FROM
`package_map`
WHERE
`package_map`.`companyID` = `company`.`companyID`
AND
`package_map`.`active` = 1
AND
`package_map`.`szekhely_endDate` > NOW()
ORDER BY
`package_map`.`szekhely_endDate` DESC
LIMIT 1
) as endDate,
CASE
WHEN endDate = NULL
FROM
`company`
WHERE
`company`.`companyBase` = 'some address'
AND
`company`.`szekhely_check_out` = 0
Use an ordinary INNER JOIN between the two tables. If there's no matching rows in the package_map table, there won't be a row in the result. To get the latest endDate, use the MAX() function.
SELECT
`company`.`companyID`,
`company`.`companyName`,
`company`.`companyName`,
`company`.`companyEmail`,
`company`.`contactEmail`,
`company`.`companyTel`,
MAX(package_map.szekhely_endDate) AS endDate
FROM company
INNER JOIN package_map ON `package_map`.`companyID` = `company`.`companyID`
WHERE
`company`.`companyBase` = 'some address'
AND
`company`.`szekhely_check_out` = 0
AND
`package_map`.`active` = 1
AND
`package_map`.`szekhely_endDate` > NOW()
GROUP BY `company`.`companyID`

auto increment using 'case' in mysql

I have a simple table in mysql that has different types of records, differentiated by a values in the column ptype
my table looks like this
id1...ptype..usr...item
1.....43.......2......7001
2.....44.......2......8001
3.....43.......2......7002
4.....43.......2......7003
5.....43.......3......7001
When I add a new record, I need my query to insert an auto incremented value in the item column, based upon ptype and specific to usr. i.e. if i insert a new record
id1...ptype..usr...item
6.....43.......3......?
it would add 1 to the highest number existing for ptype=43 and usr=3
id1...ptype..usr...item
6.....43.......3......7002
if we added another record for ptype=44 and usr=2
id1...ptype..usr...item
7.....44.......2......8002
i think i should do this by initially inserting the new record with item blank and then updating that record with information derived from the new record(i.e. #lastid) using the CASE WHEN THEN method, but it's not working.
SET #lastid := LAST_INSERT_ID();
SET #ptype = (SELECT `ptype` FROM a1 WHERE `id1` = #lastid);
SET #item = (SELECT (
CASE
when #ptype = 41 then (SELECT 1 + coalesce((SELECT max(`item`) FROM `a1` WHERE `ptype` = 41 AND `plate`=7 AND `userid` = #userid), 5000))
when #ptype = 42 then (SELECT 1 + coalesce((SELECT max(`item`) FROM `a1` WHERE `ptype` = 42 AND `plate`=7 AND `userid` = #userid), 6000))
when #ptype = 43 then (SELECT 1 + coalesce((SELECT max(`item`) FROM `a1` WHERE `ptype` = 43 AND `plate`=7 AND `userid` = #userid), 7000))
when #ptype = 44 then (SELECT 1 + coalesce((SELECT max(`item`) FROM `a1` WHERE `ptype` = 44 AND `plate`=7 AND `userid` = #userid), 8000))
when #ptype = 45 then (SELECT 1 + coalesce((SELECT max(`item`) FROM `a1` WHERE `ptype` = 45 AND `plate`=7 AND `userid` = #userid), 9000))
when #ptype = 46 then (SELECT 1 + coalesce((SELECT max(`item`) FROM `a1` WHERE `ptype` = 46 AND `plate`=7 AND `userid` = #userid), 10000))
ELSE 0
end) as item
from
a1 WHERE `id1` = #lastid);
UPDATE a1 SET item = #item WHERE id1 = #lastid
as is, #item is returning values of 0 initially, no matter what 'ptype' the new record has, and is incrementing by 1 for subsequent entries.... i need the first record added in each ptype to be 5001 6001, 7001, etc.
First, the answer for which you didn't ask: reverse your idea by creating the rows in their own tables (with an AUTO_INCREMENT as eggyal suggested) and then move the data to this table.
And now the answer:
Your information is a bit mis-matched, which might explain the problem or just be a red herring. For example, you don't describe what 'plate' is, but you use it in your query. You also use #userid, which is not set in your examples.
I created a table that seemed to match your data at the top:
create table a1 (
id1 int primary key auto_increment,
ptype int,
usr int,
item int
);
Then set the variable that you seemed to want:
set #userid = 2;
set #ptype = 43;
and inserted a row:
insert into a1 (ptype, usr) values (#ptype, #userid);
pulled the id back out as you did:
SET #lastid := LAST_INSERT_ID();
Then you can get the max 'item':
select max(item) from a1 WHERE `ptype` = #ptype AND `usr` = #userid;
To handle the initial case, you wanted a default. Since you're separating the ptypes by 1000, you can use that:
SELECT ifnull(max(`item`),(#ptype % 40 + 2)*1000)+1 as next
FROM `a1`
WHERE `ptype` = #ptype
AND `usr` = #userid;
+------+
| next |
+------+
| 5001 |
+------+
Note that this isn't thread safe, so wrap it all in a transaction/trigger.
Hope that helps.
You can use a trigger:
CREATE TRIGGER biA1 BEFORE INSERT ON a1 FOR EACH ROW SET NEW.item = (
  SELECT COALESCE(MAX(item), (NEW.ptype-36)*1000) + 1
FROM a1
WHERE ptype = NEW.ptype AND plate = 7 AND userid = NEW.userid
)