I was on the "hospital_payment_data" table.
I want to call up the data of the number of data, the cache_account_received sum, and the total_medical_bills sum, and then bring up the mount sum value from the cash_recipit_rowtable to express. What should I do?
hospital_payment_data
cash_receipt_row
I want result
However, sending the following queries results in the following:
SELECT
COUNT(*) as total,
SUM(cash_amount_received) AS sum_cash_amount_received,
COUNT(
IF(total_medical_bills >= 100000 AND
cash_amount_received , total_medical_bills, NULL)
) as obligatory_issue,
SUM(
IF(total_medical_bills >= 100000 AND
cash_amount_received , cash_amount_received, NULL)
) as sum_obligatory_issue,
SUM(amount) AS sum_amount
FROM (
SELECT total_medical_bills, cash_amount_received, amount
FROM hospital_payment_data, cash_receipt_row
) AS a
wrong result
Try this.
SELECT
COUNT(*) as total,
SUM(cash_amount_received) AS sum_cash_amount_received,
COUNT(
IF(total_medical_bills >= 100000 AND
cash_amount_received , total_medical_bills, NULL)
) as obligatory_issue,
SUM(
IF(total_medical_bills >= 100000 AND
cash_amount_received , cash_amount_received, NULL)
) as sum_obligatory_issue,
SUM(amount) AS sum_amount
FROM (
SELECT total_medical_bills, cash_amount_received, amount
FROM hospital_payment_data, cash_receipt_row
WHERE hospital_payment_data.id = cash_receipt_row.id
) AS a
Never use commas in the FROM clause. Always use proper, explicit, standard, readable JOIN syntax.
You can also simplify your counting logic in MySQL. There is no need for IF() or a subquery:
SELECT COUNT(*) as total,
SUM(cash_amount_received) AS sum_cash_amount_received,
SUM( total_medical_bills >= 100000 AND
obligatory_issue <> 0
) as obligatory_issue,
SUM(CASE WHEN total_medical_bills >= 100000
THEN cash_amount_received
END) as sum_obligatory_issue,
SUM(amount) AS sum_amount
FROM hospital_payment_data hpd JOIN
cash_receipt_row crr
ON hpd.id = crr.id;
You'll notice that where conditional logic is needed, then this uses the standard SQL construct, CASE, rather than IF.
Related
I have the following query I'm trying to use to spit out each day in a date range and show the # of leads, assignments, & returns:
select
date_format(from_unixtime(date_created), '%m/%d/%Y') as date_format,
(select count(distinct(id_lead)) from lead_history where (date_format(from_unixtime(date_created), '%m/%d/%Y') = date_format) and (id_vertical in (2)) and (id_website in (3,8))) as leads,
(select count(id) from assignments where deleted=0 and (date_format(from_unixtime(date_assigned), '%m/%d/%Y') = date_format) and (id_vertical in (2)) and (id_website in (3,8))) as assignments,
(select count(id) from assignments where deleted=1 and (date_format(from_unixtime(date_deleted), '%m/%d/%Y') = date_format) and (id_vertical in (2)) and (id_website in (3,8))) as returns
from lead_history
where date_created between 1509494400 and 1512086399
group by date_format
The date_created, date_assigned, and date_deleted fields are integers representing timestamps. id, id_lead, id_vertical and id_website are already indexed.
Would adding indexes to date_created, date_assigned, date_deleted, and deleted help make this faster? The issue I'm having is that it is very slow, and I'm not sure an index will help when using date_format(from_unixtime(...
Here is the EXPLAIN:
Looking to your code you could rewrite the query as ..
select
date_format(from_unixtime(date_created), '%m/%d/%Y') as date_format
, count(distinct(h.id_lead) as leads
, sum(case a.deleted = 1 then 1 else 0 end) assignments
, sum(case b.deleted = 0 then 1 else 0 end) returns
from lead_history h
inner join assignments on a a.date_assigned = h.date_created
and a.id_vertical = 2
and id_website in (3,8))
inner join assignments on b b.deleted = h.date_created
and a.id_vertical = 2
and id_website in (3,8))
where date_created between 1509494400 and 1512086399
group by date_format
anyway you shold avoid unuseful () and nested (), avoid unuseful conversion between date and use join instead of subselect .. or at least reduce similar sabuselect using case
PS for what concern the index remember that the use of conversion on a column value invalid the use of related the index ..
For readability, I would like to modify the below statement. Is there a way to extract the CASE statement, so I can use it multiple times without having to write it out every time?
select
mturk_worker.notes,
worker_id,
count(worker_id) answers,
count(episode_has_accepted_imdb_url) scored,
sum( case when isnull(imdb_url) and isnull(accepted_imdb_url) then 1
when imdb_url = accepted_imdb_url then 1
else 0 end ) correct,
100 * ( sum( case when isnull(imdb_url) and isnull(accepted_imdb_url) then 1
when imdb_url = accepted_imdb_url then 1
else 0 end)
/ count(episode_has_accepted_imdb_url) ) percentage
from
mturk_completion
inner join mturk_worker using (worker_id)
where
timestamp > '2015-02-01'
group by
worker_id
order by
percentage desc,
correct desc
You can actually eliminate the case statements. MySQL will interpret boolean expressions as integers in a numeric context (with 1 being true and 0 being false):
select mturk_worker.notes, worker_id, count(worker_id) answers,
count(episode_has_accepted_imdb_url) scored,
sum(imdb_url = accepted_imdb_url or imdb_url is null and accepted_idb_url is null) as correct,
(100 * sum(imdb_url = accepted_imdb_url or imdb_url is null and accepted_idb_url is null) / count(episode_has_accepted_imdb_url)
) as percentage
from mturk_completion inner join
mturk_worker
using (worker_id)
where timestamp > '2015-02-01'
group by worker_id
order by percentage desc, correct desc;
If you like, you can simplify it further by using the null-safe equals operator:
select mturk_worker.notes, worker_id, count(worker_id) answers,
count(episode_has_accepted_imdb_url) scored,
sum(imdb_url <=> accepted_imdb_url) as correct,
(100 * sum(imdb_url <=> accepted_imdb_url) / count(episode_has_accepted_imdb_url)
) as percentage
from mturk_completion inner join
mturk_worker
using (worker_id)
where timestamp > '2015-02-01'
group by worker_id
order by percentage desc, correct desc;
This isn't standard SQL, but it is perfectly fine in MySQL.
Otherwise, you would need to use a subquery, and there is additional overhead in MySQL associated with subqueries.
It is possible that this has been answered somewhere already but I couldn't find it.
So would appreciate if someone could help me with this sql statement again.
This is the sql statement which I have so far:
SELECT * , Round( (Rate * TIME_TO_SEC( Total ) /3600 ) , 2) AS revenue
FROM (SELECT event.eventID, event.staffID, event.role, TIMEDIFF( Time, Pause )
AS Total,
CASE WHEN Position = 'Teamleader'
THEN (Teamleader)
WHEN Position = 'Waiter'
THEN (Waiter)
ELSE '0'
END AS Rate
FROM event, rates, eventoverview
WHERE Storno =0
AND event.eventID= eventoverview.eventID
AND event.clientid = rates.clientid
GROUP BY event.eventID, event.clientID)q1
GROUP BY q1.staffID
The table I am getting is now giving me a total rate per staff and event.
But what I would like to achieve is a sum of those rates per staff.
So basically a sum of the revenue.
Hope someone can help me. Thanks in advance
You can enclose your query in a subquery and do that in the outer query like this:
SELECT *,
SUM(revenue)
FROM
(
SELECT * ,
Round( (Rate * TIME_TO_SEC( Total ) /3600 ) , 2) AS revenue
FROM
(
SELECT
event.eventID,
event.staffID,
event.role,
TIMEDIFF( Time, Pause ) AS Total,
CASE WHEN Position = 'Teamleader' THEN (Teamleader)
WHEN Position = 'Waiter' THEN (Waiter)
ELSE '0'
END AS Rate
FROM event
INNER JOIN rates ON event.clientid = rates.clientid
INNER JOIN eventoverview ON event.eventID = eventoverview.eventID
WHERE Storno =0
GROUP BY event.eventID, event.clientID
)q1
GROUP BY q1.staffID
) AS t
GROUP BY staffID;
Note that: You might get inconsistent data, due to the use of SELECT * with GROUP BY staffID only, the columns that are not in the GROUP BY clause need to be enclosed with an aggregate function otherwise mysql will get an arbitrary value for it. This is not recommended and it it is not the standard way to do so.
I'm trying to calculate a percentage in my SQL query.
This is what I have right now:
SELECT
DATE(processed_at) AS day,
(
SELECT
COUNT(*) FROM return_items
WHERE return_id IN (SELECT id FROM returns WHERE DATE(processed_at) = day)
) as products_returned,
COUNT(*) as return_count,
(
SELECT
COUNT(*) as co_returns
FROM returns
WHERE return_method = 'mondial_relais'
AND DATE(processed_at) = day
) as return_rate_mr
FROM returns
WHERE MONTH(processed_at) = 10
AND YEAR(processed_at) = 2011
GROUP BY day;
Basically I need the return_rate_mr to be a percentage value.
I tried doing something like return_rate_mr * 100 / return_count as perc_value but this doesn't work. (I don't actually need the current return_rate_mr value, just the percentage.
Any ideas?
Assuming your original query returns the desired results, you can wrap it as a subquery:
SELECT
day,
return_rate_mr * 100 / return_count as perc_value,
... any other columns ...
FROM
( ... your original query here ...) as myalias;
Basically, the subquery creates a result set where the columns are renamed. Then, the outer query is free to use those new column names.
Are you looking for this?
SELECT
`day`,
`products_returned`,
(`return_rate_mr` * 100) / `return_count` AS `percentage`
FROM (
SELECT
DATE(processed_at) AS day,
(
SELECT
COUNT(*) FROM return_items
WHERE return_id IN (SELECT id FROM returns WHERE DATE(processed_at) = day)
) as products_returned,
COUNT(*) as return_count,
(
SELECT
COUNT(*) as co_returns
FROM returns
WHERE return_method = 'mondial_relais'
AND DATE(processed_at) = day
) as return_rate_mr
FROM returns
WHERE MONTH(processed_at) = 10
AND YEAR(processed_at) = 2011
GROUP BY day) AS `ss`
Did you try something like:
SELECT (`return_rate_mr` * 100 ) / `return_count` as "yourValue", OthersFields
FROM SELECT
DATE(processed_at) AS day,
(
SELECT
COUNT(*) FROM return_items
WHERE return_id IN (SELECT id FROM returns WHERE DATE(processed_at) = day)
) as products_returned,
COUNT(*) as return_count,
(
SELECT
COUNT(*) as co_returns
FROM returns
WHERE return_method = 'mondial_relais'
AND DATE(processed_at) = day
) as return_rate_mr
FROM returns
WHERE MONTH(processed_at) = 10
AND YEAR(processed_at) = 2011
GROUP BY day;
Hope this helps
Try:
SELECT DATE(processed_at) AS day,
count(distinct id) as products_returned,
COUNT(*) as return_count,
100* sum(case return_method when 'mondial_relais' then 1 end) / COUNT(*)
as return_perc_mr
FROM returns
WHERE MONTH(processed_at) = 10
AND YEAR(processed_at) = 2011
GROUP BY day;
I suspect that products_returned should be counting distinct item_id values (or something similar), but this should duplicate the logic in the original query.
I wrote the following query to return some statistics about purchases made in the X amount of time. But for some reason every "COUNT" column return the total number of rows. Did I organize the query incorrectly?
SELECT COUNT(*) as countTotal, SUM(`cost`) as cost, COUNT(`paymentType` = 'credit') as count_credit, COUNT(`paymentType` = 'cash') as count_cash
FROM `purchase` WHERE `date` >= '2011-5-4'
update
I just decided to use sub-queries. This is what I ended up with.
SELECT
COUNT(*) as countTotal,
SUM(`cost`) as cost,
(SELECT COUNT(*) FROM `purchase` WHERE `paymentType` = 'credit') as count_credit,
(SELECT COUNT(*) FROM `purchase` WHERE `paymentType` = 'cash') as count_cash
FROM `purchase` WHERE `date` >= '2011-5-4'
update2
Used ypercubes answer below.
count does return the number of rows for the domain or group queried. Looks like you need to group by PaymentType to achieve what you are looking for.
SELECT PaymentType, COUNT(*) as countTotal, SUM(`cost`) as cost,
FROM `purchase`
WHERE `date` >= '2011-5-4'
Group by PaymentType
here is a reference
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html
It doesn't look correct but changing COUNT() to SUM() works fine:
SELECT COUNT(*) AS countTotal
, SUM(cost) AS cost
, SUM(paymentType = 'credit') AS count_credit --- SUM does counting here
, SUM(paymentType = 'cash') AS count_cash --- and here
FROM purchase
WHERE `date` >= '2011-05-04'
Explanation: True == 1 and False == 0 for MySQL.
You need a GROUP BY clause after your WHERE clause