See the SQL query below:
SELECT *
FROM
(SELECT
h.hotel_id AS id,h.hotel_city AS city,h.hotel_name AS hotelname,
h.hotel_star AS hotelcat, hwd.double_spl_rate, hwd.third_party_rate,
hwd.extra_bed_spl_rate, hwd.meal_plan_spl,
hwd.third_party_extra_bed, hwd.third_party_meal_plan,
hwd.room_category, hrd.hotel_rate_from, hrd.hotel_rate_to
FROM
hotels_list AS h
INNER JOIN
hotel_rate_detail AS hrd ON h.hotel_id = hrd.hotels_id
INNER JOIN
hotel_week_days AS hwd ON hrd.hotel_id = hwd.h_id
WHERE
(('2015-07-31' BETWEEN hrd.hotel_rate_from AND hrd.hotel_rate_to)
OR
('2015-08-01' BETWEEN hrd.hotel_rate_from AND hrd.hotel_rate_to)
)
AND (h.hotel_city = '1')
AND (hwd.double_spl_rate != 0 OR hwd.third_party_rate != 0)
AND (h.hotel_star = '4')
ORDER BY
hwd.double_spl_rate, hwd.third_party_rate ASC) AS result_table
GROUP BY
result_table.id
ORDER BY
result_table.double_spl_rate, result_table.third_party_rate ASC
LIMIT 0,5;
OUTPUT is attached below:
In the above output there are two columns double_spl_rate and third_party_rate which can be either 0 or a value greater than zero.
How can I create a virtual column alias which only contain values greater the zero. Let us suppose the column is final_rate which will contain values as
id | final_rate
533 | 3776
9228 | 3000
Yes, you can do this like so:
select
id,
case
when coalesce(double_spl_rate,0) = 0
then third_party_rate
else double_spl_rate
end as final_rate
from table
The coalesce operator will set double_spl_rate to 0 if it's null, and the case expression will return third_party_rate if double_spl_rate is 0.
If double_spl_rate cannot be null you can skip the coalesce part.
Note that the code above will always prefer the value in double_spl_rate and disregard the other value if both values are greater than 0. If you don't want this you could extend the logic in the case expression to account for that and return the sum of the values instead. Or you could simply just return third_party_rate + double_spl_rate in all cases.
Related
I got the following table and I need to return 1 if all rows have disponibilidad = 1
The following QUERY works just fine, but i was looking for a more efficient way of doing it.
QUERY:
SELECT IF(AVG(disponibilidad) < 1, 0, 1) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1;
RESULT:
As I see it, with an 'AND' it would be far more efficient, since it wouldn't have to do AVG().
MySql does not support a boolean AND aggregate function like Postgresql's bool_and.
Why not a simple MIN():
SELECT MIN(disponibilidad) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1;
This will return 1 only if all values of the column are 1 (provided the column is not nullable) and 0 if there is at least one row with 0.
How about something like
SELECT IF(COUNT(*)>0,0,1) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1
AND disponibilidad <> 1
so that if there are any rows where disponibilidad is not 1, you output 0, otherwise if it's zero (so all disponibilidad values are 1) you output 1?
I"m trying to add a new col that shows the rank (or sequence) of row results by date.
I've written:
SELECT
#row_number:=(CASE
WHEN #member_id = lh.member_id and lc.ladder_advocacy is not null
THEN #row_number + 1
when #member_id = lh.member_id and lc.ladder_advocacy is null then "null"
ELSE 1 /* there is an error here - i need it to return a 1 if not null, then 2 for the 2nd instance, etc */
END) AS rank_advocacy,
#member_id:=lh.member_id AS member_id,
lh.ladder_change,
lc.name,
lc.ladder_advocacy,
lc.ladder_elected,
lc.ladder_policy,
lc.ladder_engagement,
lc.ladder_newventure,
lc.ladder_collective,
lc.is_trigger
FROM
leenk_ladder_history AS lh
LEFT JOIN
leeds_so.leenk_ladder_config AS lc ON lh.ladder_config_id = lc.id
WHERE
ladder_change = 1 AND trigger_active = 1
ORDER BY member_id, trigger_event_date DESC;
There is an error at row 4, and I'm not sure how to fix it. For the first result, I want to return 1. for the second results, I want to return #row_number + 1. Third result, #row_number+2 (etc).
How do I achieve this?
I don't understand how the condition lc.ladder_advocacy is not null is being used. However, the basic structure is:
SELECT (#row_number = IF(#member_id = lh.member_id, #row_number + 1
IF(#member_id := lh.member_id, 1, 1)
)
) as rank_advocacy,
lh.ladder_change,
. . .
Some really important points:
You need to assign #member_id and #row_number in the same expression. MySQL (as with all other databases) does not guarantee the order of evaluation of expressions.
In more recent versions of MySQL, I think the ORDER BY needs to go in a subquery, with the variable expressions in the outer query.
I am stuck in a query I want to store sum result in a variable where status = 3, what happening right now is it store the value of last row and show it with all rows
Here is the query
SELECT
request_made_on,driver_id,
#sum_result = SUM(status = 3) AS complete_count,#sum_result,
SUM(status = 6) AS missed_count,
(status = 4) AS canceled_count,
sum(actual_fare),sum(discount)
from tb_engagements
group by date(request_made_on),driver_id;
and here is the screenshot,
second screenshot
I'm guessing that you want the sum of all the values:
select request_made_on, driver_id,
(#sum_result := #sum_result + SUM(status = 3)) AS complete_count,
sum(status = 6) AS missed_count,
sum(status = 4) AS canceled_count,
sum(actual_fare),
sum(discount)
from tb_engagements c cross join
(select #sum_result := 0) params
group by date(accept_time), driver_id;
Notes:
You don't need to return the value of the variable as well as the expression. The expression adds a column to the result set with the value.
You don't need if() to count values. MySQL has a nice short-hand, treating boolean expressions as integers in a numeric context.
table
create table tst(locationId int,
scheduleCount tinyint(1) DEFAULT 0,
displayFlag tinyint(1) DEFAULT 0);
INSERT INTO tst(locationId,scheduleCount)
values(5,0),(2,0),(5,1),(5,2),(2,1),(2,2);
I update multiple rows and multiple columns with one query, but want to change the one of the columns only for the first row and keep the other things the same for that column.
I want to update all the rows with some location id and change displayFlag to 1 and increment scheduleCount of only the top entry with 1 , rest would remain the same
**Query **
update tst,(select #rownum:=0) r,
set tst.displayFlag =1,
scheduleCount = (CASE WHEN #rownum=0
then scheduleCount+1
ELSE scheduleCount
END),
#rownum:=1 where locationId = 5
But it gives error and does not set the user defined variable rownum, I am able to join the tables in a select and change the value of the rownum, is there any other way to update the values.
I'm not sure this is the correct way of doing such a thing, but it is possible to include the user variable logic in the CASE condition:
UPDATE tst
JOIN (SELECT #first_row := 1) r
SET tst.displayFlag = 1,
scheduleCount = CASE
WHEN #first_row = 1 AND ((#first_row := 0) OR TRUE) THEN scheduleCount+1
ELSE scheduleCount
END
WHERE locationId = 5;
I have used a #first_row flag as this is more inline with your initial attempt.
The CASE works as follows:
On the first row #first_row = 1 so the second part of the WHEN after AND is processed, setting #first_row := 0. Unfortunately for us, the assignment returns 0, hence the OR TRUE to ensure the condition as a whole is TRUE. Thus scheduleCount + 1 is used.
On the second row #first_row != 1 so the condition is FALSE, the second part of the WHEN after AND is not processed and the ELSE scheduleCount is used.
You can see it working in this SQL Fiddle. Note; I have had to set the column types to TINYINT(3) to get the correct results.
N.B. Without an ORDER BY there is no guarantee as to what the '1st' row will be; not even that it will be the 1st as returned by a SELECT * FROM tst.
UPDATE
Unfortunately one cannot add an ORDER BY if there is a join.. so you have a choice:
Initialise #first_row outside the query and remove the JOIN.
Otherwise you are probably better off rewriting the query to something similar to:
UPDATE tst
JOIN (
SELECT locationId,
scheduleCount,
displayFlag,
#row_number := #row_number + 1 AS row_number
FROM tst
JOIN (SELECT #row_number := 0) init
WHERE locationId = 5
ORDER BY scheduleCount DESC
) tst2
ON tst2.locationId = tst.locationId
AND tst2.scheduleCount = tst.scheduleCount
AND tst2.displayFlag = tst.displayFlag
SET tst.displayFlag = 1,
tst.scheduleCount = CASE
WHEN tst2.row_number = 1 THEN tst.scheduleCount+1
ELSE tst.scheduleCount
END;
Or write two queries:
UPDATE tst
SET displayFlag = 1
WHERE locationId = 5;
UPDATE tst
SET scheduleCount = scheduleCount + 1
WHERE locationId = 5
ORDER BY scheduleCount DESC
LIMIT 1;
I am stucked with following issue,
I ve delcared a varibale (DOUBLE) in a stored procedure, and i need to assign a value (item price) from a table (item) to this declared variable. however, i need to get this value from a select query which uses case inside, the item price could be in 2 columns based on a logic i have to find the correct item price. Please help me solve this as when i execute it gives me a error,
Here how is layered,
DECLARE no_more_users INT DEFAULT 0;
DECLARE user_id INT DEFAULT 0;
DECLARE cart_id INT DEFAULT 0;
DECLARE cart_item_id INT DEFAULT 0;
DECLARE user_gift_id INT DEFAULT 0;
DECLARE itemPrice DOUBLE DEFAULT 0.0;
SELECT
CASE
WHEN sale_price=0 OR sale_price IS NULL THEN (price - ( price * discount ))
ELSE sale_price
END
INTO itemPrice
FROM item WHERE item_id = p_item_id ;
DECLARE checked_in_users CURSOR FOR
SELECT DISTINCT ul.user_id
FROM user_location ul
LEFT JOIN location_section ls ON ul.location_section_id = ls.location_section_id
INNER JOIN user u ON ul.user_id = u.user_id
INNER JOIN user_profile up ON u.user_id = up.user_id
INNER JOIN location_event le ON ul.location_event_id = le.location_event_id
WHERE ul.location_id = p_location_id AND ul.location_event_id = p_event_id
AND ul.checked_out_on IS NULL AND (ul.checked_in_on BETWEEN le.start_time AND le.end_time )
AND u.status = 1 ;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET no_more_users = 1;
OPEN checked_in_users;
FETCH checked_in_users INTO user_id;
read_loop: LOOP
some more code...
please note, sale_price, price, and discount are coulmns of item table, The logic is if sale_price is null or value is 0, then i actual sale price should be obtained from price coulmn. Finally what i need is asign corect item price in to previously declared varibale.
Any help will be highly appriciated.
There are two foms to the CASE statement, one with expressions and one with values. You are mixing them up.
with values:
CASE variable
WHEN value_1 THEN foo
WHEN value_2 THEN bar
END
with expressions:
CASE
WHEN expression_1 THEN foo
WHEN expression_2 THEN bar
END
Try
CASE
WHEN sale_price=0 OR sale_price IS NULL THEN (price - ( price * discount ))
ELSE sale_price
END
Also, you do not need the "AS correct_price" when you are using an INTO
Your select query has some problems.
The version of CASE you are are using - ie CASE var WHEN val1 THEN - doesn't work when trying to match a NILL, because in SQL null is not equal to null.
Also, you can't combine values with conditions as you hAve.
Instead, use the version if CASS that simply conditions. There are other suntactic problems. Converting your broken query then gives:
SELECT
CASE
WHEN ifnull(sale_price, 0) = 0 THEN price - (price * discount)
ELSE sale_price
END
INTO itemPrice
FROM item
WHERE item_id = p_item_id;
Note: if your table has s column called itemPrice, you must choose another name from your variable. Mysql gets confused :/