Little bit of trouble with my MySQL query - mysql

My MySQL Query
Ok so I'm trying to add another column (leave_remaining) that will display that if the leave_status is 'ok' then the leave_remaining will show the number of leave days that employee has left. I keep getting errors with this. What is the right syntax here? Thank you
This works:
select id,leave_started,leave_ended,no_of_leave_allowed,
leave_ended-leave_started AS no_of_leaves_taken,
if (leave_ended-leave_started >no_of_leave_allowed,
'leave exceeded','ok')as leave_status
from leave_taken;
This does not:
if (leave_status,'ok',
(no_leave_allowed-no_leaves_taken))as leave_remaining
from leave_taken;
select * from leave_taken;

If I'm understanding you properly, I think you want this:
SELECT
id, leave_started, leave_ended, no_of_leave_allowed,
(leave_ended - leave_started) AS no_of_leaves_taken,
IF(
(leave_ended - leave_started) > no_of_leave_allowed,
'leave exceeded',
'ok'
) AS leave_status,
IF (
(leave_ended - leave_started) > no_of_leave_allowed,
(no_of_leave_allowed - (leave_ended - leave_started)),
0
) AS leave_remaining
FROM leave_taken;
Though not sure how you have defined leave_started and leave_ended that you can subtract them like that...
http://sqlfiddle.com/#!9/16cdb3/6

SELECT has to be before the IF, altough you are not doing anything.
The correct statement is
SELECT something as alias, something_else as alias_else, if(,,) as alias_if
FROM table
WHERE where = clause
When you have to use some statement (IF or CASE for example), that result in a field, it has to be inside a select.

Related

Cannot use window function 'count' in having statement

I'm new to MYSQL, and I'm trying to validate the number of data which have the same name from 2 column that occurs more than one time, which I already try to use 'having' statement in this case and it throws me an error like this
Error Code: 3593. You cannot use the window function 'count' in this context.'
below I include an image of what I'm trying to do
you can see there a column named "number_of_same_year" represent the "COUNT OVER PARTITION" output, which has numbers that logically could be validated. I only want to show where the numbers are above 1 (which means occur more than one time)
ps: I'm using MySQL in Windows 10
You cannot use having and a window function. You would want to instead do as follows
select * from (
select unit_name
,month(transaction_date)
,year(transaction_date) as year
,budget
,count(*) over(partition by unit_name,year(transaction_date)) as number_of_same_year
from sql_advertising.history_transaction
)x
where x.number_of_same_year >1
order by x.unit_name
SELECT {fieldset}
FROM {tableset}
WHERE {conditions-1}
GROUP BY {expression-1}
HAVING {conditions-2}
AND {expression-2} = COUNT({expression-3}) OVER ({window})
Window function is applied to output dataset, but HAVING alters it. So window function cannot be used in HAVING. The above code is invalid.
You may solve it by:
WITH `cte` AS ( SELECT {fieldset},
{expression-2} = COUNT({expression-3}) OVER ({window}) AS `criteria`
FROM {tableset}
WHERE {conditions-1}
GROUP BY {expression-1}
HAVING {conditions-2} )
SELECT {fieldset}
FROM `cte`
WHERE `criteria`

mysql Query performance is low

I have a query which is running for around 2 hours in last few days. But
before that it took only 2 to 3 minutes of time. i could not able to find
the reason for its sudden slowness. Can any one help me on this?
Please find the below query explain plan[![enter image description here][1]]
[1]...
select
IFNULL(EMAIL,'') as EMAIL,
IFNULL(SITE_CD,'') as SITE_CD,
IFNULL(OPT_TYPE_CD,'') as OPT_TYPE_CD,
IFNULL(OPT_IN_IND,'') as OPT_IN_IND,
IFNULL(EVENT_TSP,'') as EVENT_TSP,
IFNULL(APPLICATION,'') as APPLICATION
from (
SELECT newsletter_entry.email email,
newsletter.site_cd site_cd,
REPLACE (newsletter.TYPE, 'OPTIN_','') opt_type_cd,
CASE
WHEN newsletter_event_temp.post_status = 'SUBSCRIBED' THEN 'Y'
WHEN newsletter_event_temp.post_status = 'UNSUBSCRIBED' THEN
'N'
ELSE ''
END
opt_in_ind,
newsletter_event_temp.event_date event_tsp,
entry_context.application application
FROM amg_toolkit.newsletter_entry,
amg_toolkit.newsletter,
(select NEWSLETTER_EVENT.* from amg_toolkit.NEWSLETTER_EVENT,
amg_toolkit.entry_context where newsletter_event.EVENT_DATE >= '2017-07-11
00:01:23' AND newsletter_event.EVENT_DATE < '2017-07-11 01:01:23' and
newsletter_event.ENTRY_CONTEXT_ID = entry_context.ENTRY_CONTEXT_ID and
entry_context.APPLICATION != 'feedbackloop') newsletter_event_temp,
amg_toolkit.entry_context
WHERE newsletter_entry.newsletter_id = newsletter.newsletter_id
AND newsletter_entry.newsletter_entry_id =
newsletter_event_temp.newsletter_entry_id
AND newsletter.TYPE IN ('OPTIN_PRIM', 'OPTIN_THRD', 'OPTIN_WRLS')
AND newsletter_event_temp.entry_context_id NOT IN
(select d.ENTRY_CONTEXT_ID from amg_toolkit.sweepstake a,
amg_toolkit.sweepstake_entry b, amg_toolkit.user_entry c,
amg_toolkit.entry_context d where a.exclude_data = 'Y' and
a.sweepstake_id=b.sweepstake_id and b.USER_ENTRY_ID=c.USER_ENTRY_ID and
c.ENTRY_CONTEXT_ID = d.ENTRY_CONTEXT_ID)
AND newsletter_event_temp.entry_context_id =
entry_context.entry_context_id
AND newsletter_event_temp.event_date >= '2017-07-11 00:01:23'
AND newsletter_event_temp.event_date < '2017-07-11 01:01:23') a;`
[1]: https://i.stack.imgur.com/cgsS1.png
dont use .*
select only the columns of data you are using in your query.
Avoid nested sub selects if you dont need them.
I don't see a need for them in this query. You query the data 3 times this way instead of just once.
Slowness can be explained by an inefficient query haveing to deal with tables that have a growing number of records.
"Not in" is resource intensive. Can you do that in a better way avoiding "not in" logic?
JOINs are usually faster than subqueries. NOT IN ( SELECT ... ) can usually be turned into LEFT JOIN ... WHERE id IS NULL.
What is the a in a.exclude_data? Looks like a syntax error.
These indexes are likely to help:
newsletter_event: INDEX(ENTRY_CONTEXT_ID, EVENT_DATE) -- in this order
You also need it for newsetter_event_temp, but since that is not possible, something has to give. What version of MySQL are you running? Perhaps you could actually CREATE TEMPORARY TABLE and ADD INDEX.

Switching lastname,firstname to firstname.lastname in sql server

I have the below data in a SQL Server 2014 column called EMP_CLASS_10_DESCR
OUELLETTE,MAXIME :845800
ANDERSON,ADRIEN :021252
MITRI,NATHALIA :687173
What I like to do is have the data represented in the following way by way of a query.
MAXIME.OUELLETTE
ADRIEN.ANDERSON
NATHALIA.MITRI
What I've done so far is
CASE WHEN CHARINDEX(':', EMP_CLASS_10_DESCR)
= 0 THEN EMP_CLASS_10_DESCR ELSE LEFT(EMP_CLASS_10_DESCR, CHARINDEX(':', EMP_CLASS_10_DESCR) - 1) END AS FULL_NAME,
But all that did was give me the following
OUELLETTE,MAXIME
ANDERSON,ADRIEN
MITRI,NATHALIA
I still need to flip the names around and replace the , (comma) with a . (period)
Any help will be much appreciated. I've done some searches but couldn't find anything close. I'm still very new to SQL Server and just trying to learn.
You can use PARSENAME:
WITH CTE AS
(
SELECT CASE
WHEN CHARINDEX(':',YourColumn) > 0
THEN RTRIM(LTRIM(LEFT(YourColumn,CHARINDEX(':',YourColumn)-1)))
ELSE YourColumn
END NewColumn
FROM dbo.YourTable
)
SELECT CONCAT(PARSENAME(REPLACE(NewColumn,',','.'),1),'.',PARSENAME(REPLACE(NewColumn,',','.'),2))
FROM CTE;

MYSQL - Select selecting rows where another column equals something

I have this query:
select feature_requests.*,
from feature_requests
where feature_requests.status in ('open','closed','indevelopment')
I also have another status - denied.
I need to also select all rows with status denied but another column on my features request table must equal something.
So something that does this:
select feature_requests.*,
from feature_requests
where feature_requests.status in ('open','closed','indevelopment','denied') and
if status = denied, instance_id = ?
Not sure of the correct syntax. Thanks for any help :)
The WHERE clause is the correct place to put these kind of conditions, but with a few differences:
SELECT `fr`.*
FROM `feature_requests` fr
WHERE (`fr`.`status` IN ('open','closed','indevelopment')) OR
((`fr`.`status` = 'denied') AND (`fr`.`instance_id` = ?))
P.S - Notice I'm using an alias for feature_requests called fr instead of writing the whole name again and again. And You don't have to write its name at all because you're using only one table in your query, but I would still use it because it reduces the chances of future mistakes.
For further reading - SELECT Syntax
From rusty memory, you're probably wanting something like this
SELECT feature_requests.* FROM feature_requests
WHERE feature_requests.status IN ('open', 'closed', 'indevelopment') OR
(feature_requests.status='denied' AND instance_id = ???)
What you have right now is pretty close.
http://www.tutorialspoint.com/sql/sql-and-or-clauses.htm
This should work:
SELECT
feature_requests.*
FROM
feature_requests
WHERE
feature_requests.status IN ('open','closed','indevelopment') OR (
feature_requests.status='denied' AND
instance_id=?
)
This can also be written without listing the table name over and over if it is the only table that you are using like this:
SELECT
*
FROM
feature_requests
WHERE
status IN ('open','closed','indevelopment') OR (
status='denied' AND
instance_id=?
)
When using AND and/or OR in your where clause please also remember to use parenthesis ( ) to show your actual meaning even when you know what takes precedence between the AND and OR. For more information on precedence of operators with MySQl Example:
color=blue AND shape=circle OR type=ball
means
(color=blue AND shape=cirlce) OR type=ball
but could easily be misinterpreted as
color=blue AND (shape=circle OR type=ball)

MySQL - help with IF... ELSE usage within query

I need to add an if/else stament inside a MySQL query but can't get it to work.
Below is an example with pseudo-code of what I want to accomplish.
SELECT *
FROM calendar
WHERE calendar.alert = 1
IF calendar.repeat = 0 THEN HAVING calendar.UTC_1 > UNIX_TIMESTAMP();
ELSE "get all records regardless of calendar.repeat value";
END IF;
Any suggestions to make this happen? I couldn't find the correct syntax for this MySQL IF ELSE.
Thanks for helping!
SELECT *
FROM calendar
WHERE calendar.alert = 1
AND CASE
WHEN `repeat` =0 THEN UTC_1 > UNIX_TIMESTAMP()
ELSE 1=1 END;
You can use IF-ELSE only inside the body of stored procedure/trigger. You can use IF(condition, value_if_condition_is_true, value_if_condition_is_false) in SELECT, but I prefer CASE(you can easily rewrite the query above to
.... AND IF(`repeat` = 0, UTC_1>UNIX_TIMESTAMP(),1=1)
Not sure I got the syntax all right here, but I like the idea of somethign like this. In my opinion it is much easier to look at in the future and see the two groups you're grabbing with the following example. I'm not educated on efficiency of case vs union in MySQL but it seems to me like the case would be less efficient as well. Maybe someone can answer that for sure?
SELECT *
FROM calendar
WHERE
calendar.alert = 1
AND calendar.repeat = 0
AND calendar.UTC_1 > UNIX_TIMTESTAMP();
UNION
SELECT *
FROM calendar
WHERE
calendar.alert = 1
AND calendar.repeat != 0