SQL SUM() across a subquery - mysql

I have a Ledger table with this schema:
LedgerId (int,not null)
Timestamp (datetime, not null)
CostCenter (int, not null)
Payee (varchar(50), not null)
Type (varchar(3),not null)
Category (varchar(24), not null)
Amount (decimal(8,2) not null)
Tag (varchar(30),null)
Memo (varchar(150), null)
where I record expense transactions for a small business.
At year's end I have to issue a form 1099 to the IRS for any contractor who received more than $600. I run the following query (thanks to StackExchange!) to get this:
SELECT Payee as Name, SUM(Amount)as Total FROM Ledger
where (convert(date,timestamp) < convert(date,'2019-01-01'))
and (convert(date,timestamp) > convert(date,'2017-12-31'))
and category like '%Contract%'
group by Payee having SUM(amount) > 600
order by Payee
This is great, and gives me a list of each contractor and the total amount for 2018.
What I would like now is a query that will give me the total amount I have spent for these contractors in 2018 (also for IRS, form 1096).
If I use this query as a subquery to obtain this total amount I get errors. How do I go about totaling all this contractor expense?

Are you saying this doesn't work?
select sum(total)
from (select Payee as Name, SUM(Amount) as Total
from Ledger
where timestamp < '2019-01-01' and
timestamp >= '2018-01-01' and
category like '%Contract%'
group by Payee
having sum(amount) > 600
) l;
You shouldn't need date conversions for the logic you want to implement.

Related

Nested Query returns nothing

In my table (named checkout) in the database I have the
price (price of the item)
discount (what percentage of discount it had, eg 50 (for 50%))
howmany (which is the quantity of the product)
date (which is the current date)
I want my query to fetch the sum of the prices that had no discount on it and the sum of the prices that had discount on it for the year that we have and group it based on the month.
In the first SELECT I get the price multiplied by the quantity and it's without discount (works perfectly fine) but when I added the sub Query, the Query does not work. Any suggestions?
The (price*(1-(discount/100) in the Sub Query, first gets the discount for example 30/100=0.3 then it substracts it from the 1 (1-0.3=0.7 ) then I multiplied it with the price (price*0.7) and it returns the price with the discount
$sqlQuery = "SELECT sum(price*howmany) as price,
(SELECT sum((price*(1-(discount/100))*howmany) as price
FROM checkout
WHERE '$year'=YEAR(date) AND discount IS NOT NULL
GROUP BY Month(date)
ORDER BY Month(date)) as discountPrice
FROM checkout
WHERE '$year'=YEAR(date) AND discount IS NULL
GROUP BY Month(date)
ORDER BY Month(date) ";
you don't need a subquery. You can put the discount condition inside the SUM() calls.
SELECT
MONTH(date) AS month,
SUM(IF(discount IS NULL, price, 0) * howmany) AS price,
SUM(IF(discount IS NOT NULL, price*(1-(discount/100))*howmany, 0) AS discountPrice
FROM checkout
WHERE YEAR(date) = $year
GROUP BY month
ORDER BY month
See need to return two sets of data with two different where clauses

mySQL query that is a bit tricky

Hi there I want to design this query in mySQL.
Statement: For all the customers that transacted during 2017, what % made another transaction within 30 days?
can you tell me how such query can be designed?
This is the picture of the table to perform this query on:
Table name is: transactions
Just use lead() to get the next date. Then aggregate at the customer level to determine if any transaction in the time period has another within 30 days for that customer.
Finally, aggregate again:
select avg(case when mindiff < 30 then 1.0 else 0 end) as within_30days
from (select customerid, min(datediff(next_date - date)) as mindiff
from (select t.*, lead(date) over (partition by customerid order by date) as next_date
from transactions t
) t
where date >= '2017-01-01' and date < '2018-01-01'
group by customerid
) c

SELECT SUM mysql

I need to select a sum of data for every day where employees belong to a department, I want to be able to select a date range and have a summary of every day is this possible, at the moment i am just getting a summary of the whole date range in one field.
This is my query at the moment
select
date,
SUM(no_of_live_products)
from
fulfilment
INNER JOIN
employee
ON employee.employee_id = fulfilment.employee_id
where
employee.department = 'Telecoms Services'
and date >= '2013-09-16'
and date <= '2013-09-29'
Is it possible to get a summary of data for every day within that date range or not?
You can
GROUP BY `date`
to see the sum per day
If you want to get the number of days and you have several time ranges,
First, get the number of dates for a single time range, then sum these up (needs a subselect).
Take this as an example, it's not a complete query for your situation:
SELECT SUM(x.days)
FROM (
SELECT TIMESTAMPDIFF(DAY, startDate, endDate) AS days
FROM fulfilment
) x
GROUP BY employee.employee_id
why not try
SELECT
date,
SUM(no_of_live_products)
FROM
fulfilment
INNER JOIN
employee ON employee.employee_id = fulfilment.employee_id
WHERE
employee.department = 'Telecoms Services'
AND date >= '2013-09-16'
AND date <= '2013-09-29'
GROUP BY date(date)

MySQL Join three different results and count

Got three results extracted from three different tables.
Each table is a product: loans, credits and discounts.
loans and credits got the following data: clientid, type, productid, date & expiration (days to go).
discounts got: clientid, date and expiration.
The results are the number of times (count) for every client which product expires in 10 days (or less) and is registered among two dates.
Example (just for loans):
SELECT clientid, COUNT(*)
FROM loans
WHERE ((type LIKE 'TITULAR') AND(date BETWEEN 'ccyy-mm-dd' AND 'ccyy-mm-dd') AND (expires <= 10))
GROUP BY clientid
ORDER BY clientid;
Obviously, not all the clients got loans, credits or discounts at the same time, but I need to get a result that sums the number of times any client has any of the products expiring in 10 days or less among the limit dates.
So, in example, if client #200 got 3 loans, 2 credits and just one discount; all of them between date1 and date2, with expiration equal or less 10; the result should be 6.
So far I've tried:
SELECT loansr.clienteid, (loansr.count + creditsr.count + discountsr.count)
FROM
(SELECT clienteid, COUNT(*) AS "count"
FROM loans
WHERE (type LIKE 'TITULAR')
AND (date BETWEEN '2009-08-01' AND '2009-10-30')
AND (expires <= 10)
GROUP BY clienteid) loansr,
(SELECT clienteid, COUNT(*) AS "count"
FROM credits
WHERE (type LIKE 'TITULAR')
AND (date BETWEEN '2009-08-01' AND '2009-10-30')
AND (expires <= 10)
GROUP BY clienteid) creditsr,
(SELECT clienteid, COUNT(*) AS "count"
FROM discounts
WHERE (date BETWEEN '2009-08-01' AND '2009-10-30')
AND (expires <= 10)
GROUP BY clienteid) discountsr
WHERE
(loansr.clienteid = creditsr.clienteid = discountsr.clienteid)
ORDER BY loansr.clienteid;
Edit 18:25
I've think that if I use UNION ALL to mix the three results and then group by clienteid I will get what I'm looking for, won't I?
SELECT clienteid AS "CLIENTE", SUM(COUNT) AS "NUM_VECES_INCI_10_ACT_U3M" FROM
((SELECT clienteid, COUNT(*) AS "COUNT"
FROM loans
WHERE (titularidad_tipo LIKE 'TITULAR')
AND (date BETWEEN '2009-08-01' AND '2009-10-30')
AND (expires >= 11)
GROUP BY clienteid)
UNION ALL
(SELECT clienteid, COUNT(*) AS "COUNT"
FROM credits
WHERE (titularidad_tipo LIKE 'TITULAR')
AND (date BETWEEN '2009-08-01' AND '2009-10-30')
AND (expires >= 11)
GROUP BY clienteid)
UNION ALL
(SELECT clienteid, COUNT(*) AS "COUNT"
FROM discounts
WHERE (date BETWEEN '2009-08-01' AND '2009-10-30')
AND (expires >= 11)
GROUP BY clienteid)) orig
GROUP BY clienteid
ORDER BY clienteid;
I'd post it in the comment if I could :)
If you use UNION ALL, you should get the desired results. Although make sure to have proper indexes (I suggest titularidad_tipo, date, expires) for tables loansr, credits, and (date, expires) for discounts table. If you have proper indexation, your results will come quickly.

Using grouped and non-grouped column in the same time

I have a table with payment requests.
PaymentId (UNSIGNED INT AI)
ClientId (USINGNED INT)
Amount (FLOAT)
PayTo (DATE)
Because for PayTo there are usually not more than 2-3 distinct values (per client) I want to create the list - how much money should be paid up to this day. Do I was looking for a query like this:
SELECT PayTo, SUM(IF(PayTo <= PayTo, Amount, 0)) as AmountThisDate
FROM Payments
WHERE ClientId='%d'
GROUP BY PayTo
ORDER BY PayTo DESC
But I'm 100% sure
PayTo <= PayTo
won't work.
What is the correct way to access GROUP BY Column and TABLE column at once if it is the same column?
It sounds like you want a cumulative sum. Here is a method using a correlated subquery:
SELECT p1.PayDate,
(select sum(p2.amount)
from Payments p2
where p2.ClientId = p.ClientId and
p2.PayDate <= p.PayDate
) as AmountThisDate
FROM Payments p1
WHERE p1.ClientId='%d'
GROUP BY p1.PayDate
ORDER BY p1.PayDate DESC;
Performance will be improved by having an index on payments(ClientId, PayDate, Amount).
SELECT PayDate, SUM(IF(PayDate <= current_date(), Amount, 0)) as AmountThisDate
FROM Payments
WHERE ClientId='%d'
GROUP BY PayDate
ORDER BY PayDate DESC
Is this what you were looking for?