Displaying data with respect to specific date? - mysql

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.

Related

How to create a MySQL Query with accumulation on a created field?

I have two tables, Invoice and Receiving, and I am using MySQL. I want to generate a balance sheet from these two tables. The result should accumulate a balance over time based on the I_Total column from Invoice and the CR_Amount column from Receiving as shown in the figures below. I have tried many queries with different joins but I am not getting the desired output.
How can I achieve the desired balance sheet with a query or function in MySQL?
If we ignore the balance column for a moment, and assuming that the date column is DATE datatype, then getting the result shown can be achieved with something like this:
SELECT t.date
, t.debit
, t.credit
FROM ( SELECT i.i_date AS date
, i.i_total AS debit
, 0 AS credit
, 'i' AS i_or_r
, i.i_id AS id
FROM invoice i
UNION ALL
SELECT r.r_date AS date
, 0 AS debit
, r.r_total AS credit
, 'r' AS i_or_r
, r.r_id AS id
FROM receiving r
) t
ORDER
BY t.date
, t.i_or_r
, t.id
To get the balance, we could do that processing on the client side, as the rows are retrieved.
NOTE: MySQL 8.0 introduces window functions, which have been available in other RDBMS such as SQL Server and Oracle (calls them "Analytic Functions").
Without window functions, to get it done in the SQL is going to be ugly.
We could make use of unsupported usage of user-defined variables. Using this approach, we would basically emulate the processing that we would do on the client side, fetching through the result that query (processing each row in order) to add/subtract from a "running balance" in a user-defined variable.
The "ugly" part about this is that it relies on behavior that is not guaranteed. The MySQL Reference Manual includes warning about it.)
Or, to get the result using pure SQL, we could use a couple of complicated looking correlated subqueries to sum up the debit and credit amounts up to the current row, and do that for each row.
It looks like we are applying debits and credits towards the balance in a similar order that a bank does, applying all of the debits and credits in date order. And on each date, we apply the debits first, and then the credits.
From the sample data and expected result, it's not clear if debits are applied ordered by amount in ascending order, or by id in ascending order.
With the sample data, we get the same balance result either way. Assuming that i_id is unique in invoice, and cr_id is unique in receiving, we can get the balance by applying credits and debits using id order as a discriminator when we're at the current date.
(If we need to apply credits on the same date in ascending amount order, the subqueries would be a little more complicated, to take into account the possibility that two credits on the same date could be for the same amount.)
SELECT t.date
, t.debit
, t.credit
, ( SELECT SUM(bi.i_total)
FROM invoice bi
WHERE bi.i_date <= t.date
AND ( bi.i_date < t.date
OR ( t.i_or_r = 'i' AND bi.i_id <= t.id )
)
)
- ( SELECT SUM(br.cr_amount)
FROM receiving br
WHERE br.cr_date <= t.date
AND ( br.cr_date < t.date
OR ( t.i_or_r = 'r' AND br.cr_id <= t.id )
OR t.i_or_r = 'i'
)
) AS balance
FROM ( SELECT i.i_date AS date
, i.i_total AS debit
, 0 AS credit
, 'i' AS i_or_r
, i.i_id AS id
FROM invoice i
UNION ALL
SELECT r.cr_date AS date
, 0 AS debit
, r.cr_amount AS credit
, 'r' AS i_or_r
, r.cr_id AS id
FROM receiving r
) t
ORDER
BY t.date
, t.i_or_r
, t.id
Try This
SELECT *, SUM(Debit) OVER(ORDER BY dt,debit ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)-SUM(Credit) OVER(ORDER BY dt,debit ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) Balance
FROM (
SELECT ID,Dt,Amount AS Debit,0 AS Credit FROM Debit
UNION ALL
SELECT ID,Dt,0 AS Debit,Amount AS Credit FROM Credit
)X
ORDER BY DT
DEMO

count sets of dates where set bigger than one

Bit of a strange question this one, I'm trying to count sets of dates - but only give one point for each set.
I dont need to count single dates e.g 03/10/2016 and 04/10/2016
Each group of dates equals one point.
data:
01/10/2016
01/10/2016 count as 1
02/10/2016
02/10/2016
02/10/2016 count as 1
03/10/2016 dont count
04/10/2016 dont count
The result im looking for would be 2 as there only 2 sets of identical dates
(01/10/2016 and 02/10/2016)
so far I have:
SELECT
COUNT(
DISTINCT (
action.`actiondate2`
)
) AS nb
FROM
ACTION
GROUP BY actiondate2
HAVING
COUNT(
DISTINCT (
action.`actiondate2`
)
) > 1
You seem to want to count dates that appear more than once. I would go with:
select count(*)
from (select a.actiondate2, count(*) as cnt
from action a
group by a.actiondate2
having count(*) > 1
) a;
EDIT:
If you want to just see the dates, use the subquery:
select a.actiondate2
from action a
group by a.actiondate2
having count(*) > 1;

Is there a way to locate/detect streaks of data from several columns at the same time in MYSQL?

I've been trying for a while to come up with a code that calculates streaks from several columns at the same time, for a table where i need to find streaks of values that are above 0. At first, i managed to use a formula that shows the rungroup, the column indicating the number of data that differs the one in question at its respective row. As shown bellow:
select descrip,
`1.01`,
(select count(*)
from `all_data` dp
where dp.`1.01` <> dpo.`1.01`
and dp.descrip <= dpo.descrip) as rungroup,
`1.02`,
(select count(*)
from `all_data` dp
where dp.`1.02` <> dpo.`1.02`
and dp.descrip <= dpo.descrip) as rungroup_2
from `all_data` dpo;
1.01 and 1.02 are the name of the columns, and descrip is used to ordenate the data. This model works so far, but i don't know how couls i use it within another query to show streaks from both columns. Would there be a way for such?
You should for sure make an UNION query with your 2 columns.
Something like this
SELECT descrip, thecol,
(select count(*)
from `all_data` dp
where (dp.`1.01` <> dpo.thecol AND dp.`1.02` <> dpo.thecol)
and dp.descrip <= dpo.descrip) as rungroup
FROM
(
SELECT *
FROM
(
SELECT '1.01' AS origcol, descrip, `1.01` AS thecol from `all_data`
UNION ALL
SELECT '1.02' AS origcol, descrip, `1.02` AS thecol from `all_data`
)
ORDER BY descrip, thecol
) dpo;
However I am totally unsure about this part :
where (dp.`1.01` <> dpo.thecol AND dp.`1.02` <> dpo.thecol)
it might be an OR instead of an AND. It is not easy without seeing the data.
Just play around with my query, decompose to get only the UNION subquery, fix... and you'll get it.

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
;

MySQL Query with Multiple Dates

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