In a MySQL group_concat() clause, I'm trying to order the resulting values of a case statement. The following query configuration properly orders things.name but does not order the 'Non-US' or 'Unknown' values within the same context.
SELECT
things.id
,group_concat(DISTINCT
CASE
WHEN things.name <> 'United States' THEN 'Non-US'
WHEN things.name IS NULL THEN 'Unknown'
ELSE things.name
END
ORDER BY name SEPARATOR ', ')
FROM things
GROUP BY things.id
I want to do something like this, but it's not working:
SELECT
things.id
,group_concat(DISTINCT
(CASE
WHEN things.name <> 'United States' THEN 'Non-US'
WHEN things.name IS NULL THEN 'Unknown'
ELSE things.name
END) AS new_name
ORDER BY new_name SEPARATOR ', ')
FROM things
GROUP BY things.id
Is there a way to sort by "new_name" without using sub-queries/ nested queries?
You can accomplish this by ordering by column position instead of column name.
For your case ORDER BY 1 should work.
SELECT
things.id
,group_concat(DISTINCT
CASE
WHEN things.name <> 'United States' THEN 'Non-US'
WHEN things.name IS NULL THEN 'Unknown'
ELSE things.name
END
ORDER BY 1 SEPARATOR ', ')
FROM things
GROUP BY things.id
A session variable might work, but I am not sure the order of evaluation within a GROUP_CONCAT():
SELECT
things.id
, group_concat(DISTINCT
#new_name := (CASE
WHEN things.name <> 'United States' THEN 'Non-US'
WHEN things.name IS NULL THEN 'Unknown'
ELSE things.name
END
) ORDER BY #new_name SEPARATOR ', ')
FROM things
GROUP BY things.id
;
If that doesn't work, you could try doing the assignment in the ORDER BY section instead, and just using #new_name in the pre-ORDER BY.
Related
How do I create an entirely new column in SQL while using CASE WHEN, GROUPING_ID(), and ROLLUP() syntax?
So far I have tried:
SELECT Country, ContactTitle, COUNT(ContactTitle) AS Count
,CASE(
WHEN
GROUPING_ID(Legend) = 0 THEN ' '
WHEN
GROUPING_ID(Legend) = 1 THEN 'SUBTOTAL(Country)')
GROUP BY ROLLUP(Country, ContactTitle)
FROM dbo.Customers
SELECT Country, ContactTitle, COUNT(ContactTitle) AS Count,
CASE
WHEN GROUPING_ID(Country,ContactTitle) = 0 THEN ''
WHEN GROUPING_ID(Country,ContactTitle) = 1 THEN CONCAT('Subtotal for ',Country)
END AS Legend
FROM dbo.Customers
GROUP BY ROLLUP(Country, ContactTitle);
A CASE needs an END.
And while testing, you could output the GROUPING_ID or GROUPING to understand what they return.
SELECT Country, ContactTitle, COUNT(*) AS Count,
(CASE
WHEN GROUPING_ID(Country, ContactTitle) = 1
THEN CONCAT('SUBTOTAL(',Country,')')
WHEN GROUPING(Country) = 1
THEN 'TOTAL'
ELSE ' '
END) AS Legend
FROM Customers
GROUP BY Country, ContactTitle WITH ROLLUP;
I am not much familiar with mysql here i am giving a portion of my query
(SELECT GROUP_CONCAT(Q.gender_id SEPARATOR ' , ') FROM path_career_gender_compatibility Q WHERE Q.data_entry_id = '1') AS career_gender_compatibility
here i am getting result as
1 , 2 , 3
but i want record like this
male,female,others
I dont know how to use a condition inside group_concat . I hope you all understand the problem any help is appreciable.
Probably you need CASE expression:
SELECT GROUP_CONCAT(case when Q.gender_id = 1 then 'male' when Q.gender_id = 2 then 'female' else 'other' end SEPARATOR ' , ')
FROM path_career_gender_compatibility Q
WHERE Q.data_entry_id = '1'
What I need:
I need to check if eventvisitor.published is 1 then increment by zero else eventvisitor is equal to 0.
mysql query
SUM(
CASE
WHEN eventvisitor.published =1
THEN eventvisitor.published=eventvisitor.published+0
ELSE eventvisitor.published=0
END
) AS eventvsisitorpublished
sql query works
$qb->select('
eve.id,
SUBSTRING(ed.value,1,150) des,
eve.membership,
eve.name,
eve.abbrName abbr_name,
eve.membership paid,
eve.wrapper event_wrapper,
(case when attach.cdnUrl is null then attach.value else attach.cdnUrl end) event_samll_wrapper,
eve.url event_url,
eve.website,
eve.eventType,
venue.name venue_name,
e.startDate,
e.endDate,
ct.name city,
c.name country,
c.url country_url,
c.shortname country_shortname,
category.id industry_id,
category.name industry_name,
category.url industry_url,
eve.status event_status,
count(distinct eventvisitor.user) PeopleAttending
')
->add('from', $from);
->innerJoin('Entities\City','ct','with','eve.city = ct.id')
->innerJoin('Entities\Country','c','with','eve.country = c.id')
->innerJoin('Entities\EventEdition','e','with','eve.eventEdition = e.id')
->innerjoin('Entities\EventCategory','cat','with','e.event = cat.event')
->innerjoin('Entities\Category','category','with','cat.category = category.id')
->leftJoin('Entities\Venue','venue','with','e.venue=venue.id')
->leftJoin('Entities\EventVisitor','eventvisitor','with','eve.id=eventvisitor.event')
//->leftJoin('Entities\Venue','v','with','v.id = e.venue')
->leftJoin('Entities\EventData','ed','with','eve.eventEdition = ed.eventEdition')
->leftJoin('Entities\Attachment','attach','with','eve.wrapperSmall = attach.id')
->Where("ed.title ='desc' or ed.title is null")
->andWhere("eve.id in (".$res.")")
->andWhere("eventvisitor.published =1")
works check in where condition.
problem I'm facing: I'm getting 500 internal error
where I have done wrong any suggestion are most welcome.
use this
SUM(
IF(eventvisitor.published ==1, eventvisitor.published , 0)
) AS eventvsisitorpublished
I have the following SQL code:
select distinct members_main.membership_type,
payment_method,sum(amount_paid)
from members_main, members_payments
where members_main.contact_id=members_payments.contact_id
group by members_main.membership_type,payment_method
That returns the following:
I want to be able to return the results in the following table grid format:
Does anyone know if or how I can do this within MySQL?
Thanks,
John
Depending on data complexity either go with bluefeet's way or if the payment_method amount is dynamic then it sounds like you need a pivot table. Try looking at this.
MySQL does not have a pivot function but you can use a CASE expression and an aggregate function to turn the rows into columns:
select m.membership_type,
sum(case when p.payment_method = 'Cash' then amount_paid else 0 end) Cash,
sum(case when p.payment_method = 'Credit Card' then amount_paid else 0 end) CreditCard,
sum(case when p.payment_method = 'Paypal' then amount_paid else 0 end) Paypal
from members_main m
inner join members_payments p
on m.contact_id=p.contact_id
group by m.membership_type;
If you are going to have an unknown number of payment_method's, then you will want to look at using a prepared statement to generate dynamic SQL:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(CASE WHEN p.payment_method = ',
payment_method,
' THEN amount_paid else 0 END) AS `',
payment_method, '`'
)
) INTO #sql
FROM members_payments ;
SET #sql
= CONCAT('SELECT m.membership_type, ', #sql, '
from members_main m
inner join members_payments p
on m.contact_id=p.contact_id
group by m.membership_type');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I am trying to get the count of females and males in the gender field of a table.
Is there a way to get the count of each in one query?
Something like:
select * from table count(where gender = 'm') as total_males, count(where gender = 'f') as total_females;
or will it require two queries?
select count(*) from table where gender = 'm';
select count(*) from table where gender = 'f';
This is basically a PIVOT. MySQL does not have a pivot so you can use an aggregate function with a CASE statement to perform this:
select
sum(case when gender = 'm' then 1 else 0 end) Total_Male,
sum(case when gender = 'f' then 1 else 0 end) Total_Female
from yourtable
See SQL Fiddle with Demo
Or using COUNT:
select
count(case when gender = 'm' then 1 else null end) Total_Male,
count(case when gender = 'f' then 1 else null end) Total_Female
from yourtable;
See SQL Fiddle with Demo
Something like this will work:
SELECT SUM(IF(t.gender='m',1,0)) AS total_males
, SUM(IF(t.gender='f',1,0)) AS total_females
FROM mytable t
The "trick" here is that we are using a conditional test to return either a 0 or a 1 for each row, and then adding up the 0's and 1's. To make this a little more clear, I am using the SUM aggregate function rather than COUNT, although COUNT could be used just as easily, though we'd need to return a NULL in place of the zero.
SELECT COUNT(IF(t.gender='m',1,NULL)) AS total_males
, COUNT(IF(t.gender='f',1,NULL)) AS total_females
FROM mytable t
Consider that the two expressions in the SELECT list of this query:
SELECT COUNT(1)
, SUM(1)
FROM mytable t
Will return the same value.
If you want to avoid the MySQL IF function, this can also be done using the ANSI SQL CASE expression:
SELECT SUM( CASE WHEN t.gender = 'm' THEN 1 ELSE 0 END )) AS total_males
, SUM( CASE WHEN t.gender = 'f' THEN 1 ELSE 0 END )) AS total_females
FROM mytable t
select sum(case when gender='m' then 1 else null end) as total_males, sum(case when gender='f' then 1 else null end) as total_females from ...
Should work just fine!
If your only issue is to avoid two queries, you can always write two queries as subselects of one query.
Select (select 1 from dual) as one, (select 2 from dual) as two from dual
This would work for your scenario, too.