Mysql exclude saturday where another value is equal to - mysql

Im having a little trouble coming to the correct syntax for my code to do what I want. Im summing up numbers of hour worked in a specific week by an employee, but I want to exclude certain days from my query. The employee can have worked for different clients, which are defined by a client_id.
Now the code below have a syntax error in the WHERE-statements inside the parantheses, and I know why, Ill just let them be there for the sake of explaining what I want to achieve in this case.
I appreciate any help you can give me.
Btw: I also tried AND( DAYOFWEEK(date) <> 7 AND client_id = '1' ) but this doesnt work either. I recon this is because my query return just a single line of result, and thus my above code doesnt do anything while the query is loop
SELECT
date,
client_id,
SUM(hours)-37.5 AS total,
SUM(lunch = 'yes') AS lunch
FROM
hours
WHERE
CONCAT(WEEK(date, 1)) = '25'
AND
CONCAT(YEAR(date)) = '2015'
AND
employee_id = '14'
AND ( DAYOFWEEK(date) <> 7 WHERE client_id = '1' )
AND ( DAYOFWEEK(date) <> 1 WHERE client_id = '2' )
AND
status = 'billed'
HAVING SUM(hours) > 37.5

You can use a bunch of logical not and and logical operators to build this logic:
SELECT
date,
client_id,
SUM(hours)-37.5 AS total,
SUM(lunch = 'yes') AS lunch
FROM
hours
WHERE
CONCAT(WEEK(date, 1)) = '25'
AND
CONCAT(YEAR(date)) = '2015'
AND
employee_id = '14'
AND NOT ( DAYOFWEEK(date) = 7 AND client_id = '1' )
AND NOT ( DAYOFWEEK(date) = 1 AND client_id = '2' )
AND
status = 'billed'
HAVING SUM(hours) > 37.5

Related

Mysql if Null or Empty String then Show N/A

Hello I'm new to mysqsl and I'm trying to display N/A if the return data is empty or NULL but my query is unrecognized statement type. What do you think is wrong with my query? wrong placement of code?
CASE when 'Earliest Time Opened' = '' or 'Earliest Time Opened' is 'Null'
then 'N/A'
ELSE
SELECT (date_format(d.date_opened, '%r') as 'Earliest Time Opened'
FROM daily_report d JOIN userinfo ui
ON d.userid= ui.id
WHERE d.date_opened >= date_sub(curdate(), interval 0 day)
AND d.survey_at_what_blh = 'Bagong Silang' AND ui.status='Employee'
ORDER BY d.date_opened DESC
limit 1
END
Use IF with ISNULL here:
SELECT IF(ISNULL(d.date_opened), 'N/A', DATE_FORMAT(d.date_opened, '%r')) AS `Earliest Time Opened`
FROM daily_report d
INNER JOIN userinfo ui ON d.userid = ui.id
WHERE
d.date_opened >= CURDATE() AND
d.survey_at_what_blh = 'Bagong Silang' AND
ui.status = 'Employee'
ORDER BY
d.date_opened DESC
LIMIT 1;
If you really wanted to use a CASE expression, then it would need to appear inside the select clause, something like this:
SELECT CASE WHEN DATE_FORMAT(d.date_opened, '%r') IS NOT NULL
THEN DATE_FORMAT(d.date_opened, '%r')
ELSE 'N/A' END AS `Earliest Time Opened`
But COALESCE is much more terse and appropriate here.

How to read from the two same dates without input the time

I have a query like below.
SELECT
occupation AS 'Contact occupation',
sum(total) AS 'Quantity'
FROM
(
SELECT
CASE
WHEN contacts.occupation IS NULL THEN 'Other'
WHEN trim(contacts.occupation) = '' THEN 'Other'
ELSE contacts.occupation
END AS occupation, count(DISTINCT(concat(patients.id, '-', individual_appointments.practitioner_id))) AS total
FROM
individual_appointments
JOIN patients ON
patients.id = individual_appointments.patient_id
JOIN practitioners ON
practitioners.id = individual_appointments.practitioner_id
JOIN businesses ON
businesses.id = individual_appointments.business_id
JOIN referral_sources ON
referral_sources.patient_id = individual_appointments.patient_id
JOIN referral_source_types ON
referral_source_types.id = referral_sources.referral_source_type_id
LEFT JOIN contacts ON
referral_sources.referring_contact_id = contacts.id
WHERE
patients.created_at BETWEEN '2018-05-22' AND '2018-05-22'
AND CONVERT(NVARCHAR(100), referral_source_types.name) = 'Contact' [[
AND {{practitioner}}]] [[
AND {{clinic}}]]
AND isnull(individual_appointments.cancelled_at, '') = ''
AND individual_appointments.did_not_arrive <> 1
GROUP BY
contacts.occupation ) marketing_referrers
GROUP BY
occupation,
marketing_referrers.total
ORDER BY
total DESC;
When I submit a date like the following patients.created_at BETWEEN '2018-05-22' AND '2018-05-22' it doesn't return anything but if I enter BETWEEN '2018-05-22' patients.created_at 'AND' 2018-05-23' it returns a value.
I think if I just input two of the same date without entering the time then the time will be 00:00:00 - 00:00:00.
How to read 00:00:00 - 23:59:59 when we input two of the same date without entering the time?
The date format in the table is filled as follows "Thursday, August 20, 2020, 9:49 AM" but it can be read if we just input the date, for example 2020-08-20.
Your help means a lot to me, thank you
if your data type is datetime then you can add:
WHERE patients.createdAt >= '2018-05-22' and patients.createdAt < '2018-05-23'
because 2018-05-22 = 2018-05-22 00:00:00
if you want to input only one date, then u can use this
WHERE patients.createdAt >= '2018-05-22 00:00:00'
AND patients.createdAt <= '2018-05-22 23:59:59'
or you can simply use this
WHERE patients.createdAt LIKE '2018-05-22%'
it will give you all of the row which has the value '2018-05-22' on it
Try using ...WHERE DATE(patients.created_at) = '2018-05-22'...

How to query last 2 business days only

I'm running a query that pulls the correct information I'm looking for, but I need it to pull the last 2 business days rather than the last 2 days. This comes into play when it's Monday and my results show information for Monday and Sunday rather than Monday and Friday. How can I change my query to pull in business days only?
USE [LetterGeneration]
SELECT g.LetterGenerationPrintJobId
,CAST(t.[TemplateKey] AS VarChar) AS LetterCode
,convert(char(12),r.CreatedDate,101) AS CreatedDate
,s.LetterGenerationStatusId AS Status
,s.StatusKey AS StatusDesc
,count(g.LetterGenerationId) as LetterCount
,c.BankingDateYorN
FROM [LetterGenerationTemplateRequest] AS r
INNER JOIN [LetterGenerationTemplate] AS t
ON t.[LetterGenerationTemplateId] = r.LetterGenerationTemplateId
INNER JOIN LetterGeneration g
ON g.LetterGenerationTemplateRequestId = r.LetterGenerationTemplateRequestId
INNER JOIN LetterGenerationStatus s
ON g.LetterGenerationStatusId = s.LetterGenerationStatusId
INNER JOIN Enterprise..Calendar C
ON c.BeginDate = g.LetterDate
WHERE ((DATEDIFF(d, r.CreatedDate, GETDATE()) = 0) OR (DATEDIFF(d, r.CreatedDate, GETDATE()) = 1))
--BankingDateYorN = 1
--AND RelativeTimeValue_BusinessDates =-1
AND t.[TemplateKey] NOT LIKE '%PLTV1%'
AND s.LetterGenerationStatusId NOT LIKE '4'
AND s.LetterGenerationStatusId NOT LIKE '16'
AND s.LetterGenerationStatusId NOT LIKE '19'
AND s.LetterGenerationStatusId NOT LIKE '20'
AND s.LetterGenerationStatusId NOT LIKE '38'
GROUP BY r.[LetterGenerationTemplateRequestId]
,r.LetterGenerationTemplateId
,g.Lettergenerationprintjobid
,t.[TemplateKey]
,r.[Loan_no]
,r.CreatedDate
,r.[CreatedBy]
,s.LetterGenerationStatusId
,s.StatusKey
,c.BankingDateYorN
ORDER BY r.CreatedDate DESC
UPDATE: I've recently discovered how to join a calendar table to my current query. The calendar query has a column called BusinessDayYorN with 1's for a business day and 0's for weekends and holidays. I've also updated the old query to now include the join.
select *
from LetterGenerationTemplateRequest
where createddate >= (
getdate() -
case datename(dw,getdate())
when 'Tuesday' then 5
when 'Monday' then 4
else 3
end
)
--and datename(dw,createdDate) not in ('Saturday','Sunday',datename(dw,getdate()))
and datename(dw,createdDate) not in ('Saturday','Sunday')
;
Assuming that you always want to include the last two non-weekend days you can try this:
; with aux as (
select diff = case
when datename(weekday, getdate()) in ('Tuesday', 'Wednesday ', 'Thursday', 'Friday') then 1
else
case datename(weekday, getdate())
when 'Saturday' then 2
when 'Sunday' then 3
when 'Monday' then 4
end
end
)
SELECT --r.[LetterGenerationTemplateRequestId]
--,r.LetterGenerationTemplateId
g.LetterGenerationPrintJobId
,CAST(t.[TemplateKey] AS VarChar) AS LetterCode
,r.[Loan_no]
,convert(char(12),r.CreatedDate,101) AS CreatedDate
-- ,g.ModifiedDate
-- ,convert(varchar(18), g.ModifiedDate - r.CreatedDate, 108) AS TimeSpan
,s.LetterGenerationStatusId AS Status
,s.StatusKey AS StatusDesc
,count(g.LetterGenerationId) as LetterCount
FROM [LetterGenerationTemplateRequest] AS r
INNER JOIN [LetterGenerationTemplate] AS t
ON t.[LetterGenerationTemplateId] = r.LetterGenerationTemplateId
INNER JOIN LetterGeneration g
ON g.LetterGenerationTemplateRequestId = r.LetterGenerationTemplateRequestId
INNER JOIN LetterGenerationStatus s
ON g.LetterGenerationStatusId = s.LetterGenerationStatusId
WHERE
DATEDIFF(day, r.CreatedDate, GETDATE()) <= (select diff from aux)
AND t.[TemplateKey] NOT LIKE '%PLTV1%'
AND s.LetterGenerationStatusId NOT LIKE '4'
AND s.LetterGenerationStatusId NOT LIKE '16'
AND s.LetterGenerationStatusId NOT LIKE '19'
AND s.LetterGenerationStatusId NOT LIKE '20'
AND s.LetterGenerationStatusId NOT LIKE '38'
GROUP BY r.[LetterGenerationTemplateRequestId]
,r.LetterGenerationTemplateId
,g.Lettergenerationprintjobid
,t.[TemplateKey]
,r.[Loan_no]
,r.CreatedDate
-- ,g.ModifiedDate
,r.[CreatedBy]
,s.LetterGenerationStatusId
,s.StatusKey
ORDER BY r.CreatedDate DESC
The CTE aux returns a dataset with only one record and only one field, the value of which is the number of days you need to go back in your WHERE statement.

SQL statement for GROUP BY

I am really stucked with one sql select statement.
This is output/result which I get from sql statement below:
WHAT I need: I need to have columns assignedVouchersNumber and usedVouchersNumber together in one row by msisdn. So for example if you can see "msisdn" 723709656 there are two rows now.. one with assignedVouchersNumber = 1 and second with assignedVouchersNumber = 1 too.
But I need to have it in one row with assignedVouchersNumber = 2. Do you now where is the problem?
SELECT eu.msisdn,
eu.id as userId,
sum(case ev.voucherstate when '1' then 1 else 0 end) as assignedVouchersNumber,
sum(case ev.voucherstate when '2' then 1 else 0 end) as usedVouchersNumber,
ev.extra_offer_id,
ev.create_time,
ev.use_time,
ev.id as voucherId,
ev.voucherstate
FROM extra_users eu
JOIN (SELECT sn.msisdn AS telcislo,
stn.numberid
FROM stats_number sn
JOIN stats_target_number AS stn
ON ( sn.numberid = stn.numberid )
WHERE stn.targetid = 1) xy
ON eu.msisdn = xy.telcislo
JOIN extra_vouchers AS ev
ON ( eu.id = ev.extra_user_id )
WHERE ev.create_time BETWEEN '2012-07-23 00:00:00' AND '2013-08-23 23:59:59'
AND ev.use_time <= '2013-08-23 23:59:59'
AND ev.use_time >= '2012-07-23 00:00:00'
AND ev.voucherstate IN ( 1, 2 )
AND Ifnull(ev.extra_offer_id IN( 2335, 3195, 30538 ), 1)
GROUP BY eu.msisdn, ev.extra_offer_id, ev.voucherState
ORDER BY eu.msisdn ASC
You have two different extra_offer_id for same msisdn and VouchersNumber. Thats why you get two rows.
I got it... there should not be groupping by ev.voucherState in
GROUP BY eu.msisdn, ev.extra_offer_id, ev.voucherState
After then I have removed ev.voucherState it is working now.

CASE Statement in SQL WHERE clause

I'm trying to fetch data from table where I'm using a CASE condition in the WHERE clause and currently I'm using following query:-
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND (
STATUS = 'Sold'
OR STATUS = 'In Stock'
OR STATUS = 'Ref'
)
AND CASE WHEN (
STATUS = 'Sold'
)
THEN delivery_date >= '2012-08-01'
END
But it returns 0 for total and NULL for purchase.
From your comment.
I want to use Case Statement, could u pls clarify me about case statament in where clause
You can use CASE statement in WHERE like this:
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND ( STATUS = 'Sold'
OR STATUS = 'In Stock'
OR STATUS = 'Ref')
AND CASE STATUS
WHEN 'Sold'
THEN delivery_date >= '2012-08-01'
ELSE 1=1
END
Here you need to use ELSE 1=1. otherwise you will not get desired result. For more explanation see this SQLFiddle
I don't think that CASE can work that way. What you want is a slightly more complex expression as your WHERE clause. Probably something like this:
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND (
(STATUS = 'Sold' AND delivery_date >= '2012-08-01')
OR STATUS = 'In Stock'
OR STATUS = 'Ref'
)