SQl query showing opposite values - mysql

Working on a sql query to show T_Temperatur and T_Badende_per_Time and the values. My sql query changes the comma to dot for the values with Cast, that is not the problem. The problem is that my sql query chose the values of the oppositite title, as you can see here:
SQL:
SELECT routines.date, routines.time,
SUM( IF( measurements.title = 'T_Temperatur', CAST( REPLACE( routines.value, ',', '.' ) AS DECIMAL( 18, 2 ) ), 0 ) ) AS T_Temperatur,
SUM( IF( measurements.title = 'T_Badende_per_Time', CAST( REPLACE( routines.value, ',', '.' ) AS DECIMAL( 18, 2 ) ), 0 ) ) AS Badende,
SUM( IF( measurements.title = 'T_Luft_temperatur', CAST( REPLACE( routines.value, ',', '.' ) AS DECIMAL( 18, 2 ) ), 0 ) ) AS Luft_Temp
FROM routines
INNER JOIN measure_routine ON routines.id = measure_routine.routine_id
INNER JOIN measurements ON measure_routine.measure_id = measurements.id
GROUP BY routines.date, routines.time
ORDER BY routines.date, routines.time;
My database is build up with
routines:
measure_routine:
measurements:

Swap the parameters in the IF() function, you return 0 if the condition is true!
IF(expr1,expr2,expr3)
If expr1 is TRUE (expr1 <> 0 and expr1 <> NULL) then IF() returns expr2; otherwise it returns expr3.
SELECT routines.date, routines.time,
SUM(IF(measurements.title='T_Temperatur', CAST(REPLACE(routines.value,',','.' ) AS DECIMAL(18,2)), 0)) AS T_Temperatur,
SUM(IF(measurements.title='T_Badende_per_Time', CAST(REPLACE(routines.value,',','.') AS DECIMAL(18,2)), 0)) AS Badende
FROM routines
INNER JOIN measure_routine ON routines.id = measure_routine.routine_id
INNER JOIN measurements ON measure_routine.measure_id = measurements.id
order by routines.date, routines.time

Related

Different results from Identical databases

I'm having an issue where my live database (MariaDB) has the exact same data as my local(MySQL) but the following query is returning the same results but in a different order (I know im not the best at SQL so I'll apologise in advance):
SELECT
`products`.*
, CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) AS `order_date`
, `category_product`.`category_id` AS `pivot_category_id`
, `category_product`.`product_id` AS `pivot_product_id`
, `count_activate`.`active_count`
, IF( `count_activate`.`product_id` > 0, 0, 1 ) AS coming_soon
FROM
`products`
INNER JOIN
`category_product`
ON
`products`.`id` = `category_product`.`product_id`
LEFT JOIN
(
SELECT
inventory.*
FROM
inventory
INNER JOIN
`booking_inventory`
ON
`inventory`.`id` = `booking_inventory`.`inventory_id`
WHERE
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) > NOW()
ORDER BY
DATE( CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) )
)
AS
inventory
ON
`products`.`id` = `inventory`.`product_id`
INNER JOIN
`booking_inventory`
ON
`inventory`.`id` = `booking_inventory`.`inventory_id`
LEFT JOIN
(
SELECT
COUNT(inventory.id) AS active_count
, product_id
FROM
inventory
INNER JOIN
`booking_inventory`
ON
`inventory`.`id` = `booking_inventory`.`inventory_id`
WHERE
status_id = 1
AND
(
stock > 0
OR stock = -1
)
AND
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) > NOW()
GROUP BY
product_id
)
AS
count_activate
ON
`count_activate`.`product_id` = `products`.`id`
WHERE
`category_product`.`category_id` = 2
AND EXISTS
(
SELECT
*
FROM
`sites`
INNER JOIN
`product_site`
ON
`sites`.`id` = `product_site`.`site_id`
WHERE
`product_site`.`product_id` = `products`.`id`
AND
`status_id` = 1
AND
`site_id` = 1
)
AND
`products`.`status_id` = 1
AND
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) > NOW()
GROUP BY
`products`.`id`
ORDER BY
`coming_soon` ASC
, `order_date` ASC
LIMIT 100
OFFSET 0
can anyone tell me whats causing this?
regards
(left id External right is Local)
EDIT
Thanks for the daft comments below and the down vote, very helpful.... After some digging, I have found the cause yet not the answer. In the second JOIN (inventory) the date ordering isn't returning the same results. If I order by the inventory id, price, SKU I get the same results across local and external data but not using the date... would anyone know why?
regards
The problem was down to the version/dbengine. The first left join has an order by in it, which I didn't realise didn't keep its order once used by the parent (depending on version/dbengine).
One way to overcome this is by setting a limit of 18446744073709551615 which forces the results to be stored in a temp table (or something, i know not what I speak!).
the other issue was inner join further down the query which forced to table to be reordered.
SELECT
IF( `counter`.`product_id` > 0, 0, 1 ) AS coming_soon,
bd.skill_level,
counter.active_count,
p.*
FROM
(
SELECT
p.*,
booking_inventory.inventory_id,
category_product.category_id,
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) as date
FROM
booking_inventory
JOIN
inventory
ON
inventory.id = booking_inventory.inventory_id
LEFT JOIN
products AS p
ON
p.id = inventory.product_id
INNER JOIN
`category_product`
ON
`p`.`id` = `category_product`.`product_id`
WHERE
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) > NOW()
AND
`category_product`.`category_id` = 2
ORDER BY
date
LIMIT
18446744073709551615
)
AS
p
LEFT JOIN
booking_data AS bd
ON
p.id = bd.product_id
LEFT JOIN
(
SELECT
COUNT(`inventory`.`id`) AS `active_count`,
`inventory`.`product_id`
FROM
`inventory`
INNER JOIN
`booking_inventory`
ON
`inventory`.`id` = `booking_inventory`.`inventory_id`
WHERE
`inventory`.`status_id` = 1
AND
(
`inventory`.`stock` > 0
OR
`inventory`.`stock` = -1
)
AND
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) > NOW()
GROUP BY
`inventory`.`product_id`
)
AS
counter
ON
`counter`.`product_id` = `p`.`id`
WHERE
EXISTS
(
SELECT
*
FROM
`sites`
INNER JOIN
`product_site`
ON
`sites`.`id` = `product_site`.`site_id`
WHERE
`product_site`.`product_id` = `p`.`id`
AND
`status_id` = 1
AND
`site_id` = 1
)
GROUP BY
p.id
ORDER BY
coming_soon,
p.date,
p.name

MySQL IN Condition Subquery

I have a question and answers listing and an option to filter the questions based on the % of correct answers. So I am using the following query for the listing :
SELECT
question_id,
text
FROM
test_answers LEFT JOIN test_questions ON test_questions.id = test_answers.question_id
LEFT JOIN test_categories ON test_questions.`category_id` = test_categories.id
WHERE `question_id` IN(question IDS)
GROUP BY `question_id`
ORDER BY `question_id` DESC;
and using another query for finding the question IDS for which the % of correct answers in the given range. The query is as follows :
SELECT q1.question_id FROM (
SELECT test_answers.question_id AS question_id,
SUM( IF( test_answers.correct_answer =1, 1, 0 ) ) AS correct_answers,
SUM( IF( test_answers.correct_answer !=1, 1, 0 ) ) AS incorrect_answers,
round( ( SUM( IF( test_answers.correct_answer =1, 1, 0 ) ) / ( SUM( IF( test_answers.correct_answer =1, 1, 0 ) ) + SUM( IF( test_answers.correct_answer !=1, 1, 0 ) ) ) *100 ) , 2 ) AS percentage
FROM test_replies
JOIN test_answers ON test_replies.answer_id = test_answers.id
GROUP BY test_answers.question_id
HAVING percentage between 80 and 89 AND correct_answers >25
) AS q1
Now the issue is that the second query returns almost 4000 question Ids and it will increase in the near future and might be become 10k or more. So I seriously would like to optimize the query as it is going to impact the performance in a great deal. Can anyone suggest a better method for doing it ?
try join instead of IN, see if it helps. (sql not tested)
SELECT
ta.question_id, text
FROM
(
SELECT test_answers.question_id AS question_id,
SUM( IF( test_answers.correct_answer =1, 1, 0 ) ) AS correct_answers,
SUM( IF( test_answers.correct_answer !=1, 1, 0 ) ) AS incorrect_answers,
round( ( SUM( IF( test_answers.correct_answer =1, 1, 0 ) ) / ( SUM( IF( test_answers.correct_answer =1, 1, 0 ) ) + SUM( IF( test_answers.correct_answer !=1, 1, 0 ) ) ) *100 ) , 2 ) AS percentage
FROM test_replies
JOIN test_answers ON test_replies.answer_id = test_answers.id
GROUP BY test_answers.question_id
HAVING percentage between 80 and 89 AND correct_answers >25
) AS q1
INNER JOIN
test_answers ta USING (question_id)
LEFT JOIN
test_questions ON test_questions.id = ta.question_id
LEFT JOIN
test_categories ON test_questions.`category_id` = test_categories.id
GROUP BY
ta.question_id`
ORDER BY
ta.question_id DESC;

Removing commas in varchar to get number and test

I have a serious problem with varchar in mysql.
This is my query :
SELECT ak.`address`, ak.lien1_amount, ak.`comp`, ak.`zestimate`, ak.`counvalue`, IFNULL(COALESCE(ak.comp, ak.zestimate, ak.counvalue), 0) AS cmazestcv, CEIL( CAST(ak.lien1_amount AS DECIMAL(10,5)) ) AS testnum
FROM allinformationk AS ak
LEFT JOIN `home_buyers_alias1` ON ak.`house id` = `home_buyers_alias1`.`house id`
WHERE ak.`is_deleted` = 'no' AND ( (CASE WHEN ak.`sale date 4` IS NOT NULL THEN ak.`sale date 4` WHEN ak.`sale date 3` IS NOT NULL THEN ak.`sale date 3` WHEN ak.`sale date 2` IS NOT NULL THEN ak.`sale date 2` ELSE ak.`sale date` END) IS NOT NULL)
AND ( CAST(IFNULL(COALESCE(ak.comp, ak.zestimate, ak.counvalue), 0) AS DECIMAL(10,5)) > CAST(ak.lien1_amount AS DECIMAL(10,5)) )
AND ak.lien1_amount IS NOT NULL
LIMIT 0, 10;
This is the result of my query :
The fields lien1_amount, comp, zestimate, counvalue are VARCHAR. This is why I am casting them to DECIMAL in my query. But still can't get it for testing as integer, you can see what lien1_amount gives in testnum column when I want to transform it to decimal.
How to change those varchar with comas to amount of money and test them ?
I can not do it since two days now.
If the said columns are of type varchar and hold numeric value always, then just replace the comma and use the result. No explicit cast is required.
And, if columns comp, zestimate, counvalue too contain comma as part of them, then apply replace on them too.
SELECT ak.`address`
, CEIL( replace( ifnull( ak.lien1_amount, 0 ), ',', '' ) ) as lien1_amount
, replace( ifnull( ak.`comp`, 0 ), ',', '' ) as `comp`
, replace( ifnull( ak.`zestimate`, 0 ), ',', '' ) as `zestimate`
, replace( ifnull( ak.`counvalue`, 0 ), ',', '' ) as `counvalue`
, replace( ifnull( COALESCE( ak.comp, ak.zestimate, ak.counvalue )
, 0 ), ',', '' ) AS cmazestcv
FROM allinformationk AS ak
LEFT JOIN `home_buyers_alias1`
ON ak.`house id` = `home_buyers_alias1`.`house id`
WHERE ak.`is_deleted` = 'no'
AND ak.lien1_amount IS NOT NULL
AND COALESCE( ak.`sale date 4`
, ak.`sale date 3`
, ak.`sale date 2`
, ak.`sale date` ) IS NOT NULL
AND replace(
IFNULL( COALESCE( ak.comp, ak.zestimate, ak.counvalue ), 0 ), ',', '' )
> replace( ak.lien1_amount, ',', '' )
LIMIT 0, 10;

How to display result and handle errors # 1242?

I want to:
if the value qty_out! = 0, then set qty_out = 0
Help me to display results
SELECT
SUBSTR(stok_control.tgl_faktur,9,2) AS 'tanggal',
SUBSTR(stok_control.tgl_faktur,6,2) AS 'bulan',
CONCAT(
(SELECT(
IFNULL(stok_control.faktur_beli,''))
)
,
(SELECT(
IFNULL(stok_control.faktur_jual,''))
)
) AS 'faktur',
bahan.id AS 'kode_bahan',
bahan.nm_bahan AS 'nama_bahan',
stok_control.qty_in AS 'masuk',
(
SELECT IF(stok_control.qty_out != '',0,0)
FROM
stok_control
WHERE
stok_control.faktur_beli !=''
) AS 'keluar'
FROM
stok_control
LEFT JOIN bahan ON stok_control.id_bahan=bahan.id
#eggyal, I have changed your code to be:
SELECT
SUBSTR(sc.tgl_faktur, 9, 2) AS 'tanggal',
SUBSTR(sc.tgl_faktur, 6, 2) AS 'bulan',
CONCAT(
IFNULL(sc.faktur_beli, ''),
IFNULL(sc.faktur_jual, '')
) AS 'faktur',
b.id AS 'kode_bahan',
b.nm_bahan AS 'nama_bahan',
(SELECT IFNULL(sc.qty_in,0)) AS 'masuk',
(SELECT
(
IF(faktur_beli <> '',
0,
(SELECT sc.qty_out)
)
)
) AS 'qty_out'
FROM
stok_control sc LEFT JOIN bahan b ON sc.id_bahan = b.id
I've tried to reference an existing but still error...
I want to:
if the value qty_out! = 0, then set qty_out = 0
Do you mean that you want qty_out to be 0 irrespective of its original value?
SELECT SUBSTR(sc.tgl_faktur, 9, 2) AS tanggal,
SUBSTR(sc.tgl_faktur, 6, 2) AS bulan,
CONCAT(
IFNULL(sc.faktur_beli, ''),
IFNULL(sc.faktur_jual, '')
) AS faktur,
b.id AS kode_bahan,
b.nm_bahan AS nama_bahan,
sc.qty_in AS masuk,
0 AS qty_out
FROM stok_control sc LEFT JOIN bahan b ON sc.id_bahan = b.id

SQL / Coalesce - Wrong row name

I have a problem with the request below!
REQUEST:
SELECT COALESCE(date(date_field), 'Total') AS "date_field_group",
COUNT( id_field ) AS "Nombre de bookings",
CONCAT( REPLACE( REPLACE( FORMAT( SUM( price1 ) , 2 ) , ',', ' ' ) , '.', ',' ) , ' €' ) AS "Total à l'achat",
CONCAT( REPLACE( REPLACE( FORMAT( SUM( price2 ) , 2 ) , ',', ' ' ) , '.', ',' ) , ' €' ) AS "Total à la vente",
CONCAT( REPLACE( REPLACE( FORMAT( SUM( price2 ) - SUM( price1 ) , 2 ) , ',', ' ' ) , '.', ',' ) , ' €' ) AS 'Marge',
CONCAT( REPLACE( FORMAT( (SUM( price2 ) / SUM( price1 ) ) , 2 ) , '1.', '' ) , ' ', '%') AS "Markup moyen"
FROM table1 S, table2 B
WHERE status_field
IN ( "1", "5")
AND DATE( date_field ) BETWEEN "2011-08-01" AND "2011-08-31"
AND type_field = "H"
AND price1 IS NOT NULL
AND S.id_field = B.id_field
AND B.id2 = "1"
GROUP BY date_field_group WITH ROLLUP
The thing is that the request is working fine (right numbers), but in the last line I was expected to get in first row "Total" and instead of that I got a field NULL...
Is someone know what is wrong with my request ?
Thx for any help ;).
You're query is almost correct (except for using implicit SQL '89 joins, which is an SQL anti-pattern)
The problem is in the last line: GROUP BY ... WITH ROLLUP.
The rollup gets applied very late in the process, after your COALESCE(date(date_field), 'Total').
So the coalesce has already finished by the time rollup comes along you need to rewrite the query like so:
SELECT COALESCE(date_field_group, 'Total') as date_field_group
, `Nombre de bookings`
, `Total à l'achat`
, `Total à la vente`
, `Marge`
, `Markup moyen`
FROM (
SELECT date(date_field) AS "date_field_group",
COUNT( id_field ) AS "Nombre de bookings",
CONCAT( REPLACE( REPLACE( FORMAT( SUM( price1 ) , 2 ) , ',', ' ' ) , '.', ',' ) , ' €' ) AS "Total à l'achat",
CONCAT( REPLACE( REPLACE( FORMAT( SUM( price2 ) , 2 ) , ',', ' ' ) , '.', ',' ) , ' €' ) AS "Total à la vente",
CONCAT( REPLACE( REPLACE( FORMAT( SUM( price2 ) - SUM( price1 ) , 2 ) , ',', ' ' ) , '.', ',' ) , ' €' ) AS 'Marge',
CONCAT( REPLACE( FORMAT( (SUM( price2 ) / SUM( price1 ) ) , 2 ) , '1.', '' ) , ' ', '%') AS "Markup moyen"
FROM table1 S
INNER JOIN table2 B ON (S.id_field = B.id_field)
WHERE status_field IN ( "1", "5")
AND DATE( date_field ) BETWEEN "2011-08-01" AND "2011-08-31"
AND type_field = "H"
AND price1 IS NOT NULL
AND B.id2 = "1"
GROUP BY date_field_group WITH ROLLUP ) AS subquery