How to put a CASE statement in the GROUP BY clause - mysql

I've got a table with one column that is a comma separated list of possible values. I'd like to query, grouped by each individual possible value.
As a test, I've written this query:
SELECT
`Please_identify_which_of_the_following_classroom_hardware_you_c2`,
count(`_How_would_you_rate_your_overall_skill_in_using_educational_tec1`) as count,
`_How_would_you_rate_your_overall_skill_in_using_educational_tec1`
FROM
`data_Copy_of_Faculty_survey_on_technology_in_the_classroom_Respo`
GROUP BY
`_How_would_you_rate_your_overall_skill_in_using_educational_tec1`,
CASE
WHEN `Please_identify_which_of_the_following_classroom_hardware_you_c2` LIKE '%Elmo%' THEN 'Elmo'
END
(Please excuse the column names, they're auto-generated)
I know the CASE statement isn't incredibly useful at this point, but I'm just trying to get the query to run. I'm getting an error:
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'THEN 'Elmo' END' at line 10
For the life of me I can't find what's wrong with the query. Any insight would be appreciated.
EDIT: I've tried with single and double quotes - same problem regardless of the quote used.
UPDATED: As Mark has pointed out, even if I get this query to parse, the results won't be what I'm looking for. I'm still curious why this doesn't parse, but the query is not the solution to my initial problem.

The reason you're seeing issues is that your GROUP BY attributes didn't align with the SELECT attributes.
As the MySql docs put it:
"SQL92 and earlier does not permit queries for which
the select list, HAVING condition, or ORDER BY list refer
to nonaggregated columns that are neither named in the GROUP BY
clause nor are functionally dependent on (uniquely determined by)
GROUP BY columns"
In other words, since the ...c2 attribute was not "functionally dependent on" your CASE ... END attribute, there was a mismatch between SELECT and GROUP BY, and thus an error.
One way to mitigate the error (and possibly make the query more readable), is to do the CASE once and then do the aggregates on the resulting relation.
SELECT c2, tec1, COUNT(tec1)
FROM
(SELECT
CASE
WHEN `Please_identify_which_of_the_following_classroom_hardware_you_c2` LIKE '%Elmo%'
THEN 'Elmo'
ELSE
`Please_identify_which_of_the_following_classroom_hardware_you_c2`
END AS c2,
`_How_would_you_rate_your_overall_skill_in_using_educational_tec1`) AS tec1
FROM
`data_Copy_of_Faculty_survey_on_technology_in_the_classroom_Respo`) t
GROUP BY c2, tec1

Try This:
SELECT
CASE
WHEN `Please_identify_which_of_the_following_classroom_hardware_you_c2` LIKE '%Elmo%' THEN 'Elmo'
ELSE `Please_identify_which_of_the_following_classroom_hardware_you_c2`
END AS `Please_identify_which_of_the_following_classroom_hardware_you_c2`,
count(`_How_would_you_rate_your_overall_skill_in_using_educational_tec1`) as count,
`_How_would_you_rate_your_overall_skill_in_using_educational_tec1`
FROM
`data_Copy_of_Faculty_survey_on_technology_in_the_classroom_Respo`
GROUP BY
`_How_would_you_rate_your_overall_skill_in_using_educational_tec1`,
CASE
WHEN `Please_identify_which_of_the_following_classroom_hardware_you_c2` LIKE '%Elmo%' THEN 'Elmo'
ELSE `Please_identify_which_of_the_following_classroom_hardware_you_c2`
END

Related

How to get count in SQL if the column value is something specific

I want to show the count in the SQL query, but I have a problem with it. I want to search for count only if there is something specific in the value column. Here is an example of my query:
SELECT COUNT(IF status='F') FROM relation WHERE from='7'
So, here I want to get the amount of "relation" from the column "status" from the table, when the status value is F.
With the above code, I get an error message:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '`status`='F') FROM `relation` WHERE `from`='7' LIMIT 0, 25' at line 1
I think two common ways are:
SELECT
COUNT(CASE WHEN status='F' THEN 1 END)
FROM relation
WHERE from='7'
and
SELECT
SUM(CASE WHEN status='F' THEN 1 ELSE 0 END)
FROM relation
WHERE from='7'
The first one uses count but since it only counts non-null values, it only counts the ones you want. The second uses sum, but since we sum 1 if your condition is true and 0 if your condition is false it's equivalent to counting where the condition is true.
Although in your case since you're not doing a group by you could just use
SELECT
COUNT(*)
FROM relation
WHERE from='7' AND status='F'
You can count this way to get only counts where the value of status is F
SELECT COUNT(*) FROM relation WHERE from='7' AND status='F';
I prefer summing a boolean expression:
SELECT SUM(status = 'F') AS cnt
FROM relation
WHERE `from` = '7';
Note that FROM is a reserved MySQL keyword. If you really did name a column FROM, then you will have to forever escape it in backticks. You should avoid naming your database objects using reserved keywords.

Use one conditional function with more than one execution path if condition is met

I have the following case statement,
case WHEN
DATE(DATE_SUB(DATE_ADD(startDate, INTERVAL 6 MONTH),INTERVAL 1 WEEK)) = DATE(NOW()) THEN
CONCAT('You should by now have held a probationary review meeting.','You must get approval from the owners.')
END AS 'emailSentence'
The emailSentence will hold the concatenation of the two sentences. This emailSentence is referenced externally by another program.
I would like to use a different alias such as emailSentence2 and refer to the second part of concat i.e. 'You must get approval from the owners.' all within the same case statement. That would mean getting rid of concat which is fine. Is there a way of doing this ? If there is a way of doing this without using a case statement i would be happy to hear that too, but it needs to be conditional statment/function.
I do realise i can use a different case statement with the same condition but that would mean multiple case statments making the sql bloated.
SQL has a very strict syntax. With * as the only exception, listing a column in a SELECT will always look like
select ... , expression [[as] alias], ...
case will be part of expression, so it cannot span multiple columns, and cannot add/return multiple columns.
Anecdotal, SQL doesn't care too much about the code being short. For example, doing something like select <expression> as value1, <expression> as value2, value1+value2 as value3 or select <expression> as value ... where value=0 is not allowed, you would have to repeat those expressions.
Nevertheless, if you really don't want to repeat that expression, you could use a left join instead and have the comparison (once) as the on-condition:
select ..., e.emailSentence, e.emailSentence2 -- or just e.*
from ...
left join (
select
'You should by now have held a probationary review meeting.' as emailSentence,
'You must get approval from the owners.' AS emailSentence2
) e on DATE(DATE_SUB(DATE_ADD(startDate, INTERVAL 6 MONTH),INTERVAL 1 WEEK)) = DATE(NOW())
To clarify: if the on-condition is not true, the values will be null, just as in the case-version.
This solution will have it's own limitations, but might be an option for you.

A Database Error Occurred Error Number: 1055 , group by substring

Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'shows.b.show_title' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
SELECT b.show_title as show_title FROM `shows` `b`
WHERE `b`.`active` = 1
GROUP BY SUBSTRING(show_title, 1, 1)
I'm naming all columns in select query so why the error?
I know the workaround of disabling ONLY_FULL_GROUP_BY from sql_mode but how do i solve the error with the query?
Q: why the error?
Consider two rows with show_title values of 'True Detective' and 'True Lies'
The expression in the GROUP BY is going to return T for both of those rows, so those rows are going to be collapsed into a single row in the resultset.
The query can return only a single value for a column in the collapsed row, and it's indeterminate/ambiguous which of the two values to return. With ONLY_FULL_GROUP_BY in sql_mode, MySQL is adhering more closely to the ANSI SQL specification; the 1055 error is behavior similar to what we observe in other relational DBMS e.g. Oracle, Microsoft SQL Server, Teradata, DB2, et al.
Q: how do i solve the error with the query?
The normative pattern is to use an aggregate function to specify which value (out of a set of possible values) to return.
For example, MAX() or MIN(). Demonstration:
SELECT SUBSTR(b.show_title,1,1) AS s1
, MAX(b.show_title) AS max_show_title
, MIN(b.show_title) AS min_show_title
FROM shows b
WHERE b.active = 1
GROUP BY SUBSTR(b.show_title,1,1)
will avoid the 1055 error, and could return e.g.
s1 max_show_title min_show_title
-- --------------- ---------------
T True Lies True Detective
Simply use these two queries and run them as query.
Your problem will be fixed asap.
No need to restart mysql
solution :
run this query :
SET sql_mode = '';
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'ONLY_FULL_GROUP_BY',''));

MySQL - Using * in a conditional statement

I am attempting to execute the following statement...
SELECT
SUM(CASE WHEN CLG ='A*' THEN 1 END) as A*
From Grades
However, I receive the following error...
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '*,"
I realise of course that * is used in select statements to select all the rows of a table. However in my case, I want to find the number of records that contain the value of A*. Would anyone be able to point out what I can do to solve this error without having to remove the A* values from my table?
You need to use backticks:
SELECT SUM(CASE WHEN CLG ='A*' THEN 1 END) as `A*`
From Grades;
Actually you could skip CASE:
SELECT SUM(CLG ='A*') as `A*`
From Grades
Your problem is the column alias. Don't use inappropriate characters for column names. Do something like this:
SELECT SUM( CLG = 'A*' ) as A_star
From Grades;
Having to deal with identifiers that use unusual characters is just a pain -- making queries hard to write and to read.

Syntax Error While Using Case Statement in Spark SQL

I want to run a case statement that runs different SELECT Statements Based on a condition in Spark SQL but not able to get the Syntax Right .
My SQL statement looks like this
registerTable(sql="SELECT CASE WHEN typedKeyword > '' THEN (SELECT * FROM `temp.sdf0` WHERE originalKeyword > ''AND keyword > '' AND deviceType = 'devicetype' ) ELSE (SELECT * FROM `temp.tes` WHERE originalKeyword > ''AND keyword > '' ) END ",alias="temp.test")
I don't know if CASE statement is supported in spark SQL so How can one achieve this
I've worked in nearly a dozen SQL and SQL-like dialects and I've never seen syntax like that. It looks like there's a core misunderstanding of what SQL clauses are supposed to do what.
The SELECT clause is for describing a projection of scalar elements. In many dialects you can issue subqueries - sometimes even correlated subqueries - in this clause, but you always must apply an operator that converts the result into a scalar value. For example:
SELECT (CASE WHEN EXISTS (SELECT foo FROM tbl) THEN 1 ELSE 0 END)
Here the "EXISTS" operator converts the uncorrelated subquery into a scalar boolean, so it's legal.
The lack of a FROM clause in the top level query is also a big red flag. It, or some analogue like Oracle's "dual", is legal in about half of the dialects I've seen, but if what you're trying to do is dynamically switch between two queries, you're almost certainly doing it wrong. juergen is right - what you probably meant to do is use 2 different queries.