I'm trying to make a select that calculates affiliate payouts.
my approach is pretty simple.
SELECT
month(payments.timestmap)
,sum(if(payments.amount>=29.95,4,0)) As Tier4
,sum(if(payments.amount>=24.95<=29.94,3,0)) As Tier3
,sum(if(payments.amount>=19.95<=24.94,2,0)) As Tier2
FROM payments
GROUP BY month(payments.timestamp)
The above does not work because MySQL is not evaluating the second part of the condition. Btw it does not cause a syntax error and the select will return results.
Before the above I tried what I was assuming would work like "amount between 24.94 AND 29.94" this caused an error. so then I tried "amount >= 24.94 AND <= 29.94"
So is it possible to have a range comparison using IF in MySql?
The second part of the expression evaluates when you use AND -
SELECT
month(payments.timestmap)
,sum(if(payments.amount>=29.95,4,0)) As Tier4
,sum(if(payments.amount>=24.95 AND payments.amount<=29.94,3,0)) As Tier3
,sum(if(payments.amount>=19.95 AND payments.amount<=24.94,2,0)) As Tier2
FROM payments
GROUP BY month(payments.timestamp)
I'm not entirely sure why the between clause didn't work for you, but the above should do the job.
There is always the BETWEEN...AND... operator in MySQL.
What error did your first attempt give you? It should definitely work. However, note that the second form you have is incorrect syntax. It should be amount >= 24.94 and amount <= 29.94.
SELECT
month( payments.timestamp )
,sum( if( payments.amount >= 29.95, 4, 0 ) ) As Tier4
,sum( if( payments.amount BETWEEN 24.95 AND 29.94, 3, 0 ) ) As Tier3
,sum( if( payments.amount BETWEEN 19.95 AND 24.94, 2, 0 ) ) As Tier2
FROM payments
GROUP BY month( payments.timestamp )
This should work also, I tested both with BETWEEN and with > < to make sure they worked the same in one of my queries. So yes, both work.
Related
I have this particular salect query which acts strange:
(1)
select date_add(
CURRENT_DATE(),
INTERVAL 7*0+(CASE
WHEN tutoring_disponibilities.day < weekday(CURRENT_DATE())
THEN 7+(tutoring_disponibilities.day-weekday(CURRENT_DATE()))
ELSE tutoring_disponibilities.day-weekday(CURRENT_DATE())
END
)
DAY
) from tutoring_disponibilities where date_add(
CURRENT_DATE(),
INTERVAL 7*0+(CASE
WHEN tutoring_disponibilities.day < weekday(CURRENT_DATE())
THEN 7+(tutoring_disponibilities.day-weekday(CURRENT_DATE()))
ELSE tutoring_disponibilities.day-weekday(CURRENT_DATE())
END
)
DAY
) NOT IN (SELECT date(tutoring_sessions.startDate) from tutoring_sessions);
This returns nothing, but this (which is the first part of the where):
(2)
select date_add(
CURRENT_DATE(),
INTERVAL 7*0+(CASE
WHEN tutoring_disponibilities.day < weekday(CURRENT_DATE())
THEN 7+(tutoring_disponibilities.day-weekday(CURRENT_DATE()))
ELSE tutoring_disponibilities.day-weekday(CURRENT_DATE())
END
)
DAY
)
from tutoring_disponibilities;
returns:
'2020-03-30'
'2020-03-30'
'2020-03-31'
'2020-03-31'
'2020-03-25'
'2020-03-25'
and this part:
(3)
SELECT date(tutoring_sessions.startDate) from tutoring_sessions;
returns this:
'2020-01-29'
NULL
NULL
NULL
'2020-02-05'
'2020-02-05'
'2020-02-10'
'2020-02-11'
'2020-02-18'
'2020-02-17'
'2020-02-25'
'2020-02-24'
'2020-03-02'
'2020-03-09'
'2020-03-16'
'2020-03-23'
'2020-02-13'
'2020-02-13'
'2020-02-13'
'2020-02-24'
'2020-02-29'
'2020-03-14'
'2020-03-30'
'2020-03-30'
'2020-03-30'
We can see that '2020-03-30'is in the results of query (3) and also in the results of query (2), but the other results of query (2) are not present in the results of query (3).
So why query(1) doesn't return anything?
If you know a better way to express this code I would be glad of any kind of help!
My recommendation is not to use NOT IN with subqueries. The reason is that any NULL value in the subquery causes no rows to be returned.
I recommend NOT EXISTS. However, your expression is rather complicated, so the simplest fix to your query is:
NOT IN (SELECT date(tutoring_sessions.startDate)
FROM tutoring_sessions
WHERE tutoring_sessions.startDate IS NOT NULL
)
With an index on tutoring_sessions(startDate), the equivalent NOT EXISTS may also be noticeably faster.
i have a order table with columns scheduled_arrival_date and actual_arrival_date , i need to find out which order delivered early and late and i need to differentiate orders based on that(two columns should be created ) , as i don't have permission to create new table so i need get this from query.
i tried this, but am getting in single column
SELECT order.id,order.item,
CASE WHEN scheduled_arrival_date >= actual_arrival_date
THEN 'late'
WHEN scheduled_arrival_date <= actual_arrival_date
THEN 'Early'
END as delivered
FROM order
SELECT order.id, order.item, 'late' AS late FROM order WHERE scheduled_arrival_date > actual_arrival_date
UNION ALL
SELECT order.id, order.item, 'early' AS early FROM order WHERE scheduled_arrival_date <= actual_arrival_date
This query is definely not optimized, but it will work. The first query gather all late shippings and put 'late' into the late column. The second one do the exact same trick but with early, and we union all of the result together.
However, i don't really understand why you want two columns, it looks weird this way, your initial request was much better IMO.
PS: Note that you should not use <= and >= in both of your condition, there is a conflit for the equal case
As you want to create a pie diagram it seems to me that you are only interested in the numbers (counts) of the two cases. You can do that like this:
SELECT COUNT(CASE WHEN actual_arrival_date-scheduled_arrival_date>0 THEN 1 END) late,
COUNT(CASE WHEN actual_arrival_date-scheduled_arrival_date<=0 THEN 1 END) early
FROM order
This query gets the output I want. In order to run it I have to run
SET sql_mode = '';
Because otherwise I get an error:
SELECT list is not in GROUP BY clause and contains nonaggregated column 'knownLoss.t1.loss' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
SELECT
t1.klDate AS LDate
, t1.Category
, t1.reason AS Reason
, sum(t1.loss) AS Loss
, round(t1.loss / t2.loss,2) AS Percentage
FROM
deptkl t1
JOIN (
SELECT
Store
, sum(loss) AS loss
FROM
deptkl
WHERE
klDate >= date_sub(SUBDATE(curdate(), WEEKDAY(curdate())), interval 7 day)
AND
klDate < SUBDATE(curdate(), WEEKDAY(curdate()))
AND
Store = 19
AND
Department = 80
) t2 ON t1.Store = t2.Store
WHERE
klDate >= date_sub(SUBDATE(curdate(), WEEKDAY(curdate())), interval 7 day)
AND
klDate < SUBDATE(curdate(), WEEKDAY(curdate()))
AND
t1.Store = 19
AND
Department = 80
GROUP BY
klDate
, Category
, reason
When I place this into the Dataset and Query Dialog of Jasper Studio, I get the same error and I am unable to use the SET sql_mode = ''; command. Any thoughts? If there is a way to achieve this without using SET sql_mode = '';?
I'm guessing the error is from this line in your select:
round(t1.loss / t2.loss,2) AS Percentage
Since you GROUP BY clause does not include this column it's somewhat of a coin toss which t1.loss and t2.loss values will be used. In some cases those values happen to always be the same based on your criteria and so you get the correct results regardless, but the db will still complain since it's being asked to return somewhat arbitrary results for those columns. One way to deal with this would be to simply apply an aggregate function to the columns in question like this:
round(min(t1.loss) / min(t2.loss),2) AS Percentage
or...
round(avg(t1.loss) / avg(t2.loss),2) AS Percentage
I think you want to do this :
round(sum(t1.loss / t2.loss)/count(*),2) AS Percentage
this will calculate the sum of the average loss for every records in the result then divide it on the the count of the record of the group it's like average of average.
EDITS:
sorry i made a syntax error now ,it should give the th wanted result and the error is because you are not using aggregate function on a column that is not in group by clause
I want to show 2 counts of the same data, one without a condition and with a condition, probably a very simple thing for most people on this list:
When I run this I get my Total of all machines:
SELECT COUNT(ComputerID) AS 'Grand Total'
FROM computers
When I run this I get the total of OnLine machines:
SELECT COUNT(ComputerID) AS 'OnLine Total'
FROM computers
WHERE LastContact > DATE_ADD(NOW(),INTERVAL -6 MINUTE)
How can I combine the 2 into 1 query to show something like this:
Grand Total OnLine Total
2,500 2,145
Thanks!
SELECT COUNT(*) AS 'Grand Total',
SUM(LastContact > DATE_ADD(NOW(), INTERVAL -6 MINUTE)) AS 'Online Total'
FROM computers
Try selecting from two separate subqueries since you don't have to group by anything. E.g.:
SELECT
(
SELECT COUNT(ComputerID)
FROM computers
) AS GrandTotal,
(
SELECT COUNT(ComputerID)
FROM computers
WHERE LastContact > DATE_ADD(NOW(),INTERVAL -6 MINUTE)
) AS OnlineTotal
Oh, and one small piece of advice! It's helpful if you provide the table schema as well. In this case, your query is pretty simple, so I didn't need much more information. But if in the future you need help with a more complex query, consider outputting the schema to something like SQLFiddle:
http://sqlfiddle.com/
Regarding Barmar's solution, it looks like there's just a missing comma after 'Grand Total' and before SUM(). It should work if you run:
SELECT COUNT(*) AS 'Grand Total',
SUM(LastContact > DATE_ADD(NOW(), INTERVAL -6 MINUTE)) AS 'Online Total'
FROM computers
Remember that an expression evaluating as true returns the value 1, and false returns 0. What you are summing is every instance of the field for which that expression holds true (2,145 trues.)
Here's another solution implementing CASE WHEN - this is essentially the same logic as the above but you can have it return anything you want under each condition. This might help to clarify how Barmar's code works - it's saying the exact same thing, just in a different way. This approach would be useful if later on down the line you wanted to count certain values a different way (e.g. count certain computers as 2, or 3, or anything):
SELECT COUNT(ComputerID) AS 'GrandTotal',
SUM(CASE WHEN LastContact > DATE_ADD(NOW(),INTERVAL -6 MINUTE)
THEN 1 ELSE 0 END) AS 'OnlineTotal'
FROM computers
I am running the following query but can't seem to get the datediff() filter to work. The query is executing successfully but even if I change the datediff() to different values I still get the same result.
SELECT project_id
, google_rank
, COALESCE(
( SELECT google_rank
FROM eig_ranking mi
WHERE mi.project_id = m.project_id
ORDER BY project_id limit 1
)
, 0) - google_rank AS movement
, keyword
, domain
FROM eig_ranking m
WHERE (DATEDIFF(rank_date, NOW())) / 7 <= 12
AND google_rank != 0
ORDER BY movement DESC
thanks for your replies. I figured it out. I am not sure if its a MYSQL bug or documentation fault but interchanging the variables in the datediff() function to DATEDIFF(NOW(), rank_date) makes it work fine for all my queries and the results are all correct