MySQL sort by column and column value - mysql

I have a situation here, I am having a join of two tables to get records, where one table is storing key value pair in two different columns(wordpress user meta table).
So heres my query:
SELECT
um.user_id
FROM
sl_job_applications as ja,
sl_usermeta as um
WHERE
um.user_id = ja.user_id
AND ja.job_id = 3
AND ja.STAGE = 'Application'
AND ja.STATUS = 'In progress'
group by ja.user_id
order by case when (um.meta_key = 'CURRENT_TOTAL_EXPERIENCE') then -1 else 2 end,
um.meta_value asc
LIMIT 0 , 50;
The order by is not working here, my data is
user_id meta_key meta_value
3 CURRENT_TOTAL_EXPERIENCE 6
4 CURRENT_TOTAL_EXPERIENCE 2
5 CURRENT_TOTAL_EXPERIENCE 1
6
I hope you understand my table data,
My above query returns
6,4,5,3
But I am expecting this output:
6,5,4,3

Simply change the order by to have an aggregation function such as max() and the value:
order by min(case when (um.meta_key = 'CURRENT_TOTAL_EXPERIENCE') then -1 else 2 end),
min(case when (um.meta_key = 'CURRENT_TOTAL_EXPERIENCE') then um.meta_value end) asc
LIMIT 0 , 50;
The first checks that the meta_key with that value exists. The second extracts the value and does the sort.

Try this:
SELECT um.user_id
FROM sl_job_applications AS ja
INNER JOIN sl_usermeta AS um ON um.user_id = ja.user_id
WHERE ja.job_id = 3 AND ja.STAGE = 'Application' AND ja.STATUS = 'In progress'
GROUP BY ja.user_id
ORDER BY CASE WHEN (um.meta_key = 'CURRENT_TOTAL_EXPERIENCE') THEN -1 ELSE 2 END,
CAST(um.meta_value AS SIGNED) ASC
LIMIT 0, 50

Related

Output of 3 queries

Got this 3 in 1 query:
SELECT * FROM
(
SELECT mesures.date j, AVG(mesures.valeur) maxi
FROM mesures
JOIN plages_horaire ON mesures.id_plage = plages_horaire.id_plage
WHERE MONTH(mesures.date) = '9' AND YEAR(mesures.date) = '2016' AND mesures.code_station = 'P02SE' AND mesures.id_crit = '1' AND mesures.id_type = '1'
GROUP BY mesures.date
) maxi
,
(
SELECT AVG(mesures.valeur) mini
FROM mesures
JOIN plages_horaire ON mesures.id_plage = plages_horaire.id_plage
WHERE MONTH(mesures.date) = '9' AND YEAR(mesures.date) = '2016' AND mesures.code_station = 'P02SE' AND mesures.id_crit = '1' AND mesures.id_type = '2'
GROUP BY mesures.date
) mini
,
(
SELECT AVG(mesures.valeur) moy
FROM mesures
JOIN plages_horaire ON mesures.id_plage = plages_horaire.id_plage
WHERE MONTH(mesures.date) = '9' AND YEAR(mesures.date) = '2016' AND mesures.code_station = 'P02SE' AND mesures.id_crit = '1' AND mesures.id_type = '3'
GROUP BY mesures.date
) moy
GROUP BY j
Problem is that I get what I want excepting values of the 2 last columns are the same at every rows:
query output
I believe it's because of the GROUP BY.
From what I can see from your query, you don't need the plage_horaire table. You can also simplify the logic greatly by using conditional aggregation:
SELECT m.date,
AVG(CASE WHEN m.id_type = 1 THEN m.valeur END) maxi,
AVG(CASE WHEN m.id_type = 2 THEN m.valeur END) mini,
AVG(CASE WHEN m.id_type = 3 THEN m.valeur END) maxmoy,
FROM mesures m
WHERE MONTH(m.date) = 9 AND YEAR(m.date) = 2016 AND
m.code_station = 'P02SE' AND m.id_crit = 1 AND m.id_type IN (1, 2, 3)
GROUP BY m.date ;
Notice that I also removed the quotes from the numeric constants. MONTH() and YEAR() return numbers, so quotes are not appropriate. I am guessing that the ids are numeric as well.

group_concat and group by are NOT working together

I have looked for the answer, but I couldn't find, so hopefully you can help me.
I'm trying to get a list of jobs grouped by 'vacatureID' and 'organisatieID'.
But I can only get one of them to work.
Could someone please advise?
Thanks.
SELECT
tblVacature.vacatureNaam,
tblVacature.vacatureCode,
DATE_FORMAT(tblVacature.vacatureDatumToegevoegd,'%d-%m'),
MAX(tblVacature.vacatureSuper),
tblOrganisatie.organisatieID,
tblOrganisatie.organisatieNaam,
tblOrganisatie.organisatieNaamConvert,
GROUP_CONCAT(tblSpecialisme.specialismeNaam
ORDER BY CASE
WHEN specialismeNaam = 'BLABLA'
THEN 1 WHEN specialismeNaam = 'BLABLA 2'
THEN 2 WHEN specialismeID = '0'
THEN 4 ELSE 3 END, specialismeNaam ASC) AS specialismeNamen,
GROUP_CONCAT(tblSpecialisme.specialismeNaamConvert
ORDER BY CASE
WHEN specialismeNaam = 'BLABLA'
THEN 1 WHEN specialismeNaam = 'BLABLA 2'
THEN 2 WHEN specialismeID = '0'
THEN 4 ELSE 3 END, specialismeNaam ASC) AS specialismeNamenConvert
FROM tblVacature
LEFT JOIN tblOrganisatie ON (tblVacature.vacatureOrganisatie = tblOrganisatie.organisatieID)
LEFT JOIN tblSpecialisme ON FIND_IN_SET(tblSpecialisme.specialismeID, REPLACE(tblVacature.vacatureSpecialisme, ' ', ','))
WHERE
vacatureActive = '1'
AND vacatureDatumToegevoegd <= ?
GROUP BY vacatureID, organisatieID
ORDER BY MAX(vacatureSuper) DESC, tblVacature.vacatureDatumToegevoegd DESC

How can I select the rest of the row with DISTINCT?

I have a table where I keep messages and one where I keep users.
I want to get all the users that interactioned (send or received a message) with user_id 1.
This query works:
http://sqlfiddle.com/#!2/6a2f3/1
EDIT:
SELECT DISTINCT
(CASE WHEN `user_to_id` = 1 THEN `user_from_id` ELSE `user_to_id` END) `user_id`,
users.*
FROM `messages`
INNER JOIN users
ON (CASE WHEN `user_to_id` = 1 THEN `user_from_id` ELSE `user_to_id` END) = users.user_id
WHERE `user_to_id` = 1 OR `user_from_id` = 1
ORDER BY `time` DESC
But if I add to SELECT the message column, it returns duplicate records:
http://sqlfiddle.com/#!2/6a2f3/2
EDIT:
SELECT DISTINCT
(CASE WHEN `user_to_id` = 1 THEN `user_from_id` ELSE `user_to_id` END) `user_id`,
`messages`.`message`,
users.*
FROM `messages`
INNER JOIN users
ON (CASE WHEN `user_to_id` = 1 THEN `user_from_id` ELSE `user_to_id` END) = users.user_id
WHERE `user_to_id` = 1 OR `user_from_id` = 1
ORDER BY `time` DESC
How can I fix that?
And also, I see that it orders the results after the "DISTINCT" selection was made. The first query should return the results inverted because the row with message_id 2 has time 3.
Is there a way I can order them before the "DISTINCT"?
EDIT 2: I wasn't clear about the question. I want to select only the last message for a matched user_id.
Do you want something like this?
SELECT *
FROM (
SELECT
users.*,
(SELECT `message` from messages
WHERE
(CASE WHEN `user_to_id` = 1 THEN `user_from_id` ELSE `user_to_id` END) = users.user_id
AND (`user_to_id` = 1 OR `user_from_id` = 1)
ORDER BY `time` DESC limit 1
) AS message
FROM users
) a
WHERE message IS NOT NULL
SQL Fiddle
It's not returning duplicate records, you have two records with User_ID = 2.
I'm confused by what you want them to be ordered by. If you want to order them in the inverted order, just remove 'DESC'

Is it possible to change the order by "DESC/ASC" in a case statment - MySql

I have a select statement with a order by command. Now the order by command has a case statment based on the status of the record it sort by a different column. However, I need to also the order by DESC if the status = 1 else order by ASC.
How can I do this?
This is my current statement:
SELECT ph.phone_call_id AS id, ph.call_subject AS callSubject,
ph.trigger_on AS triggerOn,
ph.isAppointment,
IFNULL(ph.last_attempt_on, "") last_attempt_on,
ind.name AS industry,
ac.account_id,
ac.account_name AS accountName
FROM phone_calls AS ph
INNER JOIN accounts AS ac ON ph.account_id = ac.account_id
INNER JOIN industries AS ind ON ind.industry_id = ac.industry_id
INNER JOIN call_codes AS cc ON ph.call_code_id = cc.call_code_id
WHERE ac.status = 1
AND ph.status = '.$call_status.'
AND ph.owner_id = '. USER_ID .'
AND ac.do_not_call = 0
ORDER BY CASE WHEN ph.status = 1 THEN ph.trigger_on ELSE ph.last_attempt_on END
Is this what you want?
ORDER BY (CASE WHEN ph.status = 1 THEN ph.trigger_on end) DESC,
(case when ph.status <> 1 then ph.last_attempt_on END) ASC

MySQL select subqueries

This is what I have at the moment.
$db =& JFactory::getDBO();
$query = $db->getQuery(true);
$query->select('`#__catalog_commit`.`id` as id, `#__catalog_commit`.`date` as date, COUNT(`#__catalog_commit_message`.`commit_id`) as count,
(SELECT COUNT(`#__catalog_commit_message`.`type`) as count_notice FROM `#__catalog_commit_message` WHERE `#__catalog_commit_message`.`type` = 1 GROUP BY `#__catalog_commit_message`.`type`) as count_notice,
(SELECT COUNT(`#__catalog_commit_message`.`type`) as count_warning FROM `#__catalog_commit_message` WHERE `#__catalog_commit_message`.`type` = 2 GROUP BY `#__catalog_commit_message`.`type`) as count_warning,
(SELECT COUNT(`#__catalog_commit_message`.`type`) as count_error FROM `#__catalog_commit_message` WHERE `#__catalog_commit_message`.`type` = 3 GROUP BY `#__catalog_commit_message`.`type`) as count_error');
$query->from('#__catalog_commit_message');
$query->leftjoin('`#__catalog_commit` ON `#__catalog_commit`.`id` = `#__catalog_commit_message`.`commit_id`');
$query->group('`#__catalog_commit_message`.`commit_id`');
$query->order('`#__catalog_commit`.`id` DESC');
What I have is 2 tables with the following structures:
catalog_commit
==============
id
date
catalog_commit_message
======================
id
commit_id
type
message
Basically I want to have the count of each different types of messages per group items. In what I have it actually select every rows (Which is normal) but I'm looking for a way (nicier if possible) to have the count per messages type within the query.
EDIT: Just wanted to add that it's a JModelList.
From what I gather, this should be your query:
SELECT c.id
,c.date
,count(cm.commit_id) as ct_total
,sum(CASE WHEN cm.type = 1 THEN 1 ELSE 0 END) AS count_notice
,sum(CASE WHEN cm.type = 2 THEN 1 ELSE 0 END) AS count_warning
,sum(CASE WHEN cm.type = 3 THEN 1 ELSE 0 END) AS count_error
FROM catalog_commit c
LEFT JOIN catalog_commit_message cm ON cm.commit_id = c.id
GROUP BY c.id, c.date
ORDER BY c.id DESC
You had the order of your tables reversed in the LEFT JOIN. Also, you had weird subqueries in the SELECT list.