MySQL Query with Multiple Dates - mysql

I'm trying to pull some activity reports for an application based on date ranges (number of "Stars" for each post)
It has a post table that includes and account id, and an "affiliate" table that ties that id to an account.
I know that I can do:
SELECT
posts.affid,
affiliates.name
sum(posts.stars) AS SEPT_2012
from posts
JOIN affiliates on posts.affid = affiliates.id
WHERE posts.timestamp BETWEEN '2012-09-01' AND '2012-10-01'
group by affid
That will pull a result that has the affiliate ID, Name and total "stars" from September. A single month
However, I'd like to do a pull that goes back and gets numbers for August, July, June and May that would display in a single query result (so the result would include affid, name, SEPT_2012, AUG_2012, JUL_2012...etc). Essentially, doing subqueries for those other date ranges, I assume.
Any suggestions?
Thanks for your help!

You probably want to GROUP BY EXTRACT(YEAR_MONTH FROM timestamp) (in addition to whatever else you want to do). Of course it will not get you the SEPT_2012, AUG_2012, etc. columns, but the data will be there.

While you won't be able to dynamically create the columns, you can "fake" them and use a UNION for each date range. Inside each UNION, you select 0 for the other date columns and the SUM() for the correct column.
Something similar to this should work:
SELECT
posts.affid,
affiliates.name,
sum(posts.stars) AS SEPT_2012,
0 AS AUG_2012,
0 AS JUL_2012
from
posts
JOIN affiliates on posts.affid = affiliates.id
WHERE
posts.timestamp BETWEEN '2012-09-01' AND '2012-10-01'
group by affid
UNION (
SELECT
posts.affid,
affiliates.name
0 AS SEPT_2012,
sum(posts.stars) AS AUG_2012,
0 AS JUL_2012
from
posts
JOIN affiliates on posts.affid = affiliates.id
WHERE
posts.timestamp BETWEEN '2012-08-01' AND '2012-09-01'
group by affid
)
UNION (
SELECT
posts.affid,
affiliates.name
0 AS SEPT_2012,
0 AS AUG_2012,
sum(posts.stars) AS JUL_2012
from
posts
JOIN affiliates on posts.affid = affiliates.id
WHERE
posts.timestamp BETWEEN '2012-07-01' AND '2012-08-01'
group by affid
)
UPDATE (to combine all results for each affid on a single row)
Per a comment, you would like to combine the results for each posts.affid on a single row with all of the data in each column. You can achieve this by putting an outer-query around the full query above and then using GROUP BY affid again. With this, you should have a single row for each affid and all of the columns as requested. I've updated the above query to select 0 for each empty column instead of null for "nicer" output too:
SELECT affid, name, SEPT_2012, AUG_2012, JUL_2012 FROM (
... full query above ...
) AS q
GROUP BY affid
UPDATE
To get the sum of all "stars" from all subqueries, the outer select statement works with:
SELECT affid, name, sum(SEPT_2012), sum(AUG_2012), sum(JUL_2012) FROM (
... full query above ...
) AS q
GROUP BY affid

Related

How to stop this repetition and group by date

After multiple attempts I'm unable to get my required result from this query.
SELECT
cc.date as credi_date,
cd.date as debit_date,
cd.month AS month,
ROUND(IFNULL(cc.credit_amount,0),2) AS credit,
ROUND(IFNULL(cd.debit_amount,0),2) AS debit
FROM
(SELECT
DATE(cc.credit_date) as date,
MONTHNAME(cc.credit_date) as month,
IFNULL(SUM(cc.credit_amount),0) AS credit_amount
FROM
cust_credit cc
WHERE YEAR(cc.credit_date) = YEAR(NOW())
GROUP BY DATE(cc.credit_date)) cc
INNER JOIN
(SELECT
DATE(cd.debit_date) as date,
MONTHNAME(cd.debit_date) as month,
IFNULL(SUM(cd.debit_amount),0) AS debit_amount
FROM
cust_debit cd
WHERE YEAR(cd.debit_date) = YEAR(NOW())
GROUP BY DATE(cd.debit_date)) cd ON cc.month=cd.month
The problem is that this query repeats the rows multiple times. I don't know what thing cause this repetition and how can fix this. The image of result is given below.
My required result is
My credit table is give below
My debit table is give below
Yon should use a UNION in the subquery and then GROUP BY in the SELECT:
SELECT my_date,
my_month,
SUM(credit),
SUM(debit)
FROM (
SELECT cc.credit_date as my_date,
MONTHNAME(cc.credit_date) as my_month,
ROUND(SUM(IFNULL(cc.credit_amount,0)),2) AS credit,
0 AS debit
FROM cust_credit cc
WHERE YEAR(cc.credit_date) = YEAR(NOW())
GROUP BY cc.credit_date,
MONTHNAME(cc.credit_date)
UNION
SELECT
cd.debit_date ,
MONTHNAME(cd.debit_date) ,
0 ,
ROUND(SUM(IFNULL(cd.debit_amount,0)),2)
FROM cust_debit cd
WHERE YEAR(cd.debit_date) = YEAR(NOW())
GROUP BY cd.debit_date,
MONTHNAME(cd.debit_date)
) as TT
GROUP BY my_date,my_month
This is the Fiddle
Basically, your result is cross join between two query and that's the reason your are getting cross product i.e. total number of rows from credit x total number of rows from debit.
Because, month for all rows in debit and credit tables are same (i.e. January). But, you have unique date in both table
So, making below change should give you expected output.
ON cc.month=cd.month
to
ON cc.date = cd.date

how to count number of lines with jointure in Talend on Oracle

i have 3 tables
supplier(id_supp, name, adress, ...)
Customer(id_cust, name, adress, ...)
Order(id_order, ref_cust, ref_supp, date_order...)
I want to make a job that counts the number of orders by Supplier, for last_week, last_two_weeks with Talend
select
supp.name,
(
select
count(*)
from
order
where
date_order between sysdate-7 and sysdate
nd ref_supp=id_supp
) as week_1,
(
select
count(*)
from
order
where
date_order between sysdate-14 and sysdate-7
nd ref_supp=id_supp
) as week_2
from supplier supp
the resaon for what i'm doing this, is that my query took to much time
You need a join between supplier and order to get supplier names. I show an inner join, but if you need ALL suppliers (even those with no orders in the order table) you may change it to a left outer join.
Other than that, you should only have to read the order table once and get all the info you need. Your query does more than one pass (read EXPLAIN PLAN for your query), which may be why it is taking too long.
NOTE: sysdate has a time-of-day component (and perhaps the date_order value does too); the way you wrote the query may or may not do exactly what you want it to do. You may have to surround sysdate by trunc().
select s.name,
count(case when o.date_order between sysdate - 7 and sysdate then 1 end)
as week_1,
count(case when o.date_order between sysdate - 14 and sysdate - 7 then 1 end)
as week_2
from supplier s inner join order o
on s.id_supp = o.ref_supp
;

Select count of customers that purchased at least one from two specific categories in the same month

I'm trying to write a query to count the customers that purchased at least one from order_type=0 and one order_type=1 during the same month in 2014
I have two tables.
The order table that have:
order_id
customer_id
aquisition_date
orders_category table:
order_id
order_type (the type of the orders it may have 0, 1, 2, 3, 5, 8 ...etc )
I tried with this query but it didn't work, I know it's not complete and I missed the month condition!
Select count(user_id) From order
join orders_category
on order.order_id = orders_category.order_id
Where (order_type=0 or order_type=1)
and extract (year from order.aquisition_date)=2014
group by user_id
having count (case when type_id=0 then null else null end) > 0
and count (case when type_id=1 then null else null end) > 0;
I don't know how to find users with at least 1 order from order_type=0 & 1 order of order_type=1, in the same month.
You could use this query, based on what you already had. However, I suggest you change the name of the table order to orders as order is a reserved word:
select count(distinct user_id)
from (
select user_id, month(aquisition_date)
from orders
inner join order_category
on orders.order_id = order_category.order_id
where order_type in (0, 1)
and year(aquisition_date) = 2014
group by user_id, month(aquisition_date)
having count(distinct order_type) = 2
) as base
SQL fiddle
I selected the month also in the sub-select, as it will be interesting to look at the output of that query on its own during your analysis.

Displaying data with respect to specific date?

I am trying to make a reporting system where I need to display report
for each date.
These is my table schema for selected_items
This is stock_list
I am using php in the back-end and java in the front end to display
the data. I tried a couple of queries to get the desired output but so
far I am not able to get it.These are some of the queries i used.
SELECT
COALESCE(stock_list.date, selected_items.date) AS date,
SUM( stock_list.qty ) AS StockSum,
SUM( stock_list.weight ) AS Stockweight,
COUNT( selected_items.barcode ) AS BilledItems,
SUM( selected_items.weight ) AS Billedweight
FROM stock_list join selected_items
ON stock_list.date = selected_items.date
GROUP BY COALESCE(stock_list.date, selected_items.date)
ORDER BY COALESCE(stock_list.date, selected_items.date);
This gives me the first five columns but the output gives me wrong values.
Then I also tried Union.
SELECT SUM( qty ) AS StockSum, SUM( weight ) AS Stockweight
FROM `stock_list`
WHERE DATE LIKE '08-Jan-2016'
UNION SELECT COUNT( barcode ) AS BilledItems, SUM( weight ) AS Billedweight
FROM `selected_items`
WHERE DATE LIKE '08-Jan-2016'
UNION SELECT SUM( qty ) AS TotalStock, SUM( weight ) AS TotalWeight
FROM `stock_list`;
Here I get the correct values for four columns but the problem is the >result is displayed in two columns when I would like it to be in 4 columns.
Can anyone guide me please I have figured the java part of it but I am not good at php and mysql.
Thank you
Unfortunately, SQL Fiddle crashed while I was trying to execute this query
SELECT sl.date AS date, B.qtySum AS StockSum, B.weightSum AS Stockweight,
C.barcodeCount AS BilledItems, C.weightSum AS Billedweight
FROM stock_list sl
JOIN (SELECT SUM(qty) as qtySum, SUM(weight) as weightSum
FROM STOCK_LIST GROUP BY date) AS B
ON B.date = sl.date
JOIN (SELECT SUM (weight) AS weightSum, COUNT(barcode) AS barcodeCount
FROM SELECTED_ITEMS GROUP BY date) AS C
ON C.date = sl.date;
As it was tried here. The problem with joins is that the rows will be joined multiple times and thus, the sum goes awry. For example, you have four rows that are joined from the second table and so the sum is four times higher as it should. With subqueries you can avoid this problem as you count and sum up variables before joining them and therefore, the numbers should fit. Alas, I couldn't run the query so I'm not 100% sure it works, but it should be the right approach.

How to use query results in another query?

I am trying to write a query which will give me the last entry of each month in a table called transactions. I believe I am halfway there as I have the following query which groups all the entries by month then selects the highest id in each group which is the last entry for each month.
SELECT max(id),
EXTRACT(YEAR_MONTH FROM date) as yyyymm
FROM transactions
GROUP BY yyyymm
Gives the correct results
id yyyymm
100 201006
105 201007
111 201008
118 201009
120 201010
I don’t know how to then run a query on the same table but select the balance column where it matches the id from the first query to give results
id balance date
120 10000 2010-10-08
118 11000 2010-09-29
I've tried subqueries and looked at joins but i'm not sure how to go about using them.
You can make your first select an inline view, and then join to it. Something like this (not tested, but should give you the idea):
SELECT x.id
, t.balance
, t.date
FROM your_table t
/* here, we make your select an inline view, then we can join to it */
, (SELECT max(id) id,
EXTRACT(YEAR_MONTH FROM date) as yyyymm
FROM transactions
GROUP BY yyyymm) x
WHERE t.id = x.id