MySQL - How can I do a conditional WHERE and OR clause Query? - mysql

Problem 1:
I need to add a field in a WHERE clause with a condition in my stored procedure, so what is the right syntax for the below query in CASE condition?
Problem 2:
OR condition is giving me all records with values 0,1,2,3,4 for below condition (I need tqm.is_imp = 1 if not found then tqm.is_imp IN (0,2,3,4)). What should I do? Please help.
tqm.is_imp = 1 OR tqm.is_imp IN (0,2,3,4)
My Query:
SELECT tqm.id INTO selectedQuestionNumber
FROM tc_question_master tqm
INNER JOIN tc_question_mapping tqmap ON tqmap.tc_question_id = tqm.id
WHERE tqmap.syllabus_chapter_details_id IN (SELECT cms_id from topic where chapter_id IN (SELECT id from MyChapters))
AND tqm.marks = CurMark
CASE WHEN CurQuestionType > 0 THEN
AND tqm.question_type = CurQuestionType
END
AND (tqm.level_of_question = 'Easy' OR tqm.level_of_question
IN ('Moderate','Difficult','Very difficult'))
AND (tqm.is_imp = 1 OR tqm.is_imp IN (0,2,3,4))
AND tqm.id NOT IN (SELECT q.question_id FROM QBDetails q)
ORDER BY RAND() LIMIT 1;

The upper part is just a reformat, but lower as you approach the logic that was a case expression, most of that is pure guess.
SELECT
tqm.id INTO selectedQuestionNumber
FROM tc_question_master tqm
INNER JOIN tc_question_mapping tqmap ON tqmap.tc_question_id = tqm.id
WHERE tqmap.syllabus_chapter_details_id IN (
SELECT
cms_id
FROM topic
WHERE chapter_id IN (
SELECT
id
FROM MyChapters
)
)
AND (
tqm.level_of_question = 'Easy'
OR tqm.level_of_question IN ('Moderate', 'Difficult', 'Very difficult')
)
AND (
tqm.is_imp = 1
OR tqm.is_imp IN (0, 2, 3, 4)
)
AND tqm.id NOT IN (
SELECT
q.question_id
FROM QBDetails q
)
## now it is really vague
AND (
tqm.marks = CurMark
OR
(CurQuestionType > 0 AND tqm.question_type = CurQuestionType)
)
## end of guesswork
ORDER BY
RAND()
LIMIT 1;

Related

Should I find correct MySQL query or optimize database structure?

I have database of following structure:
TABLE ingredients (ingredient_name, color)
TABLE recipes (recipe_name)
TABLE recipes_ingredients_parts (recipe_name, ingredient_name, parts)
What I want is to get a recipe that corresponds with selected ingredients and their number. So what I`ve tried first was query:
SELECT rr.* FROM
(SELECT r.* FROM receipes r
INNER JOIN receipes_ingredients_parts ri
ON r.receipe_name = ri.receipe_name
AND ri.ingredient_name = 'espresso'
AND ri.parts_number = '1') rr;
And what I get are {"Americano", "Espresso"}. But that should be "Espresso" only because for "Americano" there should be the query:
SELECT rr.* FROM
(SELECT r.* FROM receipes r
INNER JOIN receipes_ingredients_parts ri
ON r.receipe_name = ri.receipe_name
AND ri.ingredient_name = 'espresso'
AND ri.parts_number = '1') rr
INNER JOIN receipes_ingredients_parts ri
ON rr.receipe_name = ri.receipe_name
AND ri.ingredient_name = 'water'
AND ri.parts_number = '4';
Next my idea was to alter recipe table and add columns for each ingredient to store it's quantity for the recipe. But it would be near 20 columns of that kind. So I'm confused with thought that I'm doing job in a bad style. Maybe I should use some good query for the purpose? Do you guys have any ideas about all the stuff?
I think this is what you are looking for, it should find receipe_names that have all the ingredients in your list, and no other ingredients.
SELECT receipe_name
, SUM(CASE
WHEN (ingredient_name, parts_number) IN (('espresso','1'))
THEN 1 ELSE 0
END
) AS matchedIngredients
, SUM(CASE
WHEN (ingredient_name, parts_number) NOT IN (('espresso','1'))
THEN 1 ELSE 0
END
) AS otherIngredients
FROM receipes_ingredients_parts
GROUP BY receipe_name
HAVING matchedIngredients = 1 AND otherIngredients = 0
A more generalized version/template:
SELECT aField
, SUM(CASE
WHEN someField IN ([matchList])
THEN 1
ELSE 0
END
) AS matches
, SUM(CASE
WHEN someField NOT IN ([matchList])
THEN 1
ELSE 0
END
) AS others
FROM aTable
GROUP BY aField
HAVING matches = [# of values in matchlist]
AND others = 0
Alternatively, if items in the matchlist might be repeated in the table for an "aField" value:
SELECT aField
, COUNT(DISTINCT CASE
WHEN someField IN ([matchList])
THEN someField
ELSE NULL
END
) AS matches
, COUNT(DISTINCT CASE
WHEN someField NOT IN ([matchList])
THEN someField
ELSE NULL
END
) AS others
FROM aTable
GROUP BY aField
HAVING matches = [# of values in matchlist]
AND others = 0

Adding a WHERE condition on an IF alias in a MySQL query

I'm having trouble adding a condition on aliases is_paid, is_overdue and is_outstanding in the following query:
SELECT r.doc_number,
r.doc_date,
r.due_date,
r.currency,
r.amount,
r.vat,
r.vatammount,
(r.amount + r.vatammount) final_amount,
r.currency,
b.boq_id,
b.boq_comp_id,
b.boq_client_id,
b.boq_agency,
b.boq_date,
b.boq_orders,
b.receivable_id,
c.comp_name,
crm.`cn-name-first`,
crm.`cn-name-last`,
bi.inv_path,
(SELECT SUM(amount_recieved)
FROM receivables_payments
WHERE r_id = b.receivable_id) total_amount_received,
IF (r.amount + r.vatammount =
(SELECT SUM(amount_recieved)
FROM receivables_payments
WHERE r_id = b.receivable_id),
'1',
'0') AS is_paid,
IF (CURRENT_DATE >= r.due_date
AND r.amount + r.vatammount !=
(SELECT SUM(amount_recieved)
FROM receivables_payments
WHERE r_id = b.receivable_id),
'1',
'0') AS is_overdue,
IF (r.due_date < CURRENT_DATE
AND r.amount + r.vatammount !=
(SELECT SUM(amount_recieved)
FROM receivables_payments
WHERE r_id = b.receivable_id),
'1',
'0') AS is_outstanding
FROM receivables r
LEFT JOIN boq b ON b.receivable_id = r.id
LEFT JOIN boq_invoices bi ON bi.inv_boq_id = b.boq_id
LEFT JOIN comp_companies c ON c.comp_id = b.boq_comp_id
LEFT JOIN crm_contacts crm ON crm.contact_id = b.boq_client_id
WHERE r.status = 'active'
AND r.doc_type = 'inv'
AND b.boq_status = 'active'
AND is_paid = '1'
ORDER BY r.doc_date DESC LIMIT 10
Is there any way to modify this query and to make it possible to add a condition on those three aliases?
use alias in where condition .. is not allowed . because .is not possibile
the query code is evaluted based on a specified order .. starting from FROM then
WHERE clause and last the SELECT and the column alias so .. when the where is performed the column alias is not available at the query
You could try with an having condition because having work on the result of the query and not on the raw rows value .. (this could have effect on performance ..because all the query is performed and only the result is filtered by having)

Mysql EXISTS not recognizing Alias of previous table

What I try to achieve is the following, I have a Hierarchical table with data.
Each category may have 3 subcategories(maximum).
So I want to check if the subordinated subcategories have subcategories(descendants) and in the last AND condition if they have products.
The problem is that my ALIAS tree1 is not recognized in the last AND condition.
/* SQL Error (1054): Unknown column 'tree1.Node_ID' in 'on clause' */
Here is my query, any help would be appreciated.
SELECT tree1.Node_ID, tree1.Bez,
IF(EXISTS(SELECT * FROM `301` as tree2 WHERE tree2.Node_Parent_ID <=> tree1.Node_ID LIMIT 1),1,0) as descendants
FROM `301` as tree1
WHERE tree1.TreeTypNr = 1
AND tree1.Node_Parent_ID <=> 100001
AND EXISTS(
SELECT * FROM `400`
INNER JOIN `302` ON `302`.Node_ID = tree1.Node_ID
WHERE `400`.GenArtNr = `302`.GenArtNr
AND `400`.VknZielNr = 18302
AND `400`.VknZielArt = 2
LIMIT 1
)
I've swapped two rows:
`400`.GenArtNr = `302`.GenArtNr (put in ON cluase)
and
`302`.Node_ID = tree1.Node_ID (put in WHERE condition)
Try this:
SELECT tree1.Node_ID, tree1.Bez,
IF(EXISTS(SELECT * FROM `301` as tree2 WHERE tree2.Node_Parent_ID <=>
tree1.Node_ID LIMIT 1),1,0) as descendants
FROM `301` as tree1
WHERE tree1.TreeTypNr = 1
AND tree1.Node_Parent_ID <=> 100001
AND EXISTS(
SELECT * FROM `400`
INNER JOIN `302` ON `400`.GenArtNr = `302`.GenArtNr
WHERE `302`.Node_ID = tree1.Node_ID
AND `400`.VknZielNr = 18302
AND `400`.VknZielArt = 2
LIMIT 1
)

SQL Query behavior

I'm bogged in trying to figure out why query a is returning different records than query b. Both queries have seemingly same purpose yet a is returning 500 and b 3500.
this is query a:
SELECT DISTINCT ODE.OrderBillToID
FROM APTIFY.dbo.vwVwOrderDetailsKGExtended ODE
WHERE ProductID IN (2022, 1393)
AND LTRIM(RTRIM(ODE.OrderStatus)) <> 'Cancelled'
AND LTRIM(RTRIM(ODE.OrderType)) <> 'Cancellation'
AND LTRIM(RTRIM(ODE.cancellationStatus)) <> 'FULLY CANCELLED'
UNION
SELECT DISTINCT ID
FROM APTIFY.dbo.vwPersons WHERE City = 'A'
UNION
SELECT DISTINCT RecordID
FROM APTIFY.dbo.vwTopicCodeLinks WHERE TopicCodeID = 16 AND Value = 'Yes, Please'
query b:
SELECT
APTIFY..vwPersons.ID
FROM
APTIFY..vwPersons
WHERE
( APTIFY..vwPersons.ID IN (
SELECT
vwMeetingRegistrants.ID
FROM
APTIFY.dbo.vwMeetings vwMeetings
INNER JOIN APTIFY.dbo.vwMeetingRegistrants vwMeetingRegistrants
ON vwMeetings.ID=vwMeetingRegistrants.ActualMeetingID WHERE
vwMeetings.ProductID = 2022
)
OR
APTIFY..vwPersons.ID IN (
SELECT
vwMeetingRegistrants.ID
FROM
APTIFY.dbo.vwMeetings vwMeetings
INNER JOIN APTIFY.dbo.vwMeetingRegistrants vwMeetingRegistrants
ON vwMeetings.ID=vwMeetingRegistrants.ActualMeetingID WHERE
vwMeetings.ProductID = 1393
)
OR
APTIFY..vwPersons.City = N'Albany' )
OR
((
APTIFY..vwPersons.ID IN (
SELECT
RecordID
FROM
APTIFY.dbo.vwTopicCodeLinks vwTopicCodeLinks
WHERE
vwTopicCodeLinks.TopicCodeID = 16
)
AND
APTIFY..vwPersons.ID IN (
SELECT
RecordID
FROM
APTIFY.dbo.vwTopicCodeLinks vwTopicCodeLinks
WHERE
vwTopicCodeLinks.Value = N'Yes, Please'
) )
)
vwMeetingsRegistrants from the b query are producing the same records as orderkgdetailsextended from query. I cannot see ANY difference in those queries - which perhaps shows my lack of understanding the query behaviour.
BIG Thanks for any points guys! :)
As it came out, incorrectly structured query is a result of badly configured application, Aptify.

MySQL SELECT while UPDATE

I wrote a query, and Im sure that it was right form.
But I get an error. :)
May I do this query else?
UPDATE pages SET
p_name = 'Activites',
p_active = 1,
p_parent = 'sport',
p_parent_id=(
SELECT p_id FROM pages WHERE p_link='sport' LIMIT 1
),
p_link = 'activites'
WHERE p_id = 9;
Thank you.
You can't do that this way. You need to cross join the table and subquery:
UPDATE
pages AS p
CROSS JOIN (
SELECT p_id FROM pages WHERE p_link='sport' LIMIT 1
) AS sq
SET
p.p_name = 'Activites',
p.p_active = 1,
p.p_parent = 'sport',
p.p.parent_id= sq.p_id
p.p_link = 'activites'
WHERE p.p_id = 9;