SQL query to make 2 sums from the same field - php

I am trying to have the total "amount" with "type" = 1 and with type = 2 by year of the "created_at" field.
Here is the table
+-----------------+------------------+------+
| Field | Type | Null |
+-----------------+------------------+------+-----
| id | int(10) unsigned | NO |
| type | int(10) unsigned | YES |
| type | varchar(255) | NO |
| amount | double(11,2) | NO |
| created_at | timestamp | YES |
| updated_at | timestamp | YES |
Here is my code (It only gives the total for type = 1):
DB::select(
'SELECT
year,
created_at,
type,
SUM(amount) AS total
FROM
(SELECT
YEAR(created_at) AS year,
amount,
created_at,
type
FROM table
WHERE type= 1) AS t
GROUP BY year, type
ORDER BY year;
');
thanks in advance for any help.

I suspect you really want conditional aggregation:
SELECT YEAR(created_at) AS year,
SUM(CASE WHEN type = 1 THEN amount ELSE 0 END) as amount_1,
SUM(CASE WHEN type = 2 THEN amount ELSE 0 END) as amount_2
FROM table
GROUP BY YEAR(created_at);

You just need one simple query for this. Take the year of the date, sum the amount and group by year and type. FYI, you have type as a field twice in your question. That's not possible, so I'm assuming that it's really some other field name the second time.
SELECT
YEAR(created_at) AS year,
type,
SUM(amount) AS amount
FROM mytable
GROUP BY YEAR(created_at), type
ORDER BY YEAR(created_at)
DEMO

Your question needs more clarification but I assumed you wanted to compare type 1 amount per year,created at, type to the total yearly amount.
select year(created_at), created_at, type,
sum(case when type =1 then amount else 0 end) as type1amount,
sum(amount) over (partition by year(created_at)) as yeartotal
from table
group by 1,2,3

Related

MySQL PHP select rows count in date range

I have a MySQL table for product orderings named TABLE1.
Date means the date purchase has been made
The table has other columns that currently have no influence.
PRODUCT_ID | DATE | other columns
3 |2018-02-01 | other values
3 |2018-02-03 | other values
3 |2018-02-07 | other values
3 |2018-02-07 | other values
3 |2018-03-02 | other values
I know that the first time the product 3 has been ordered, is 2018-02-01
SELECT DATE FROM TABLE1 WHERE PRODUCT_ID = '3' ORDER BY DATE ASC LIMIT 1
How do I select count of product orderings per day within range of 2018-02-01 and 2019-03-16 (today) so that I could get a table like that:
DATE | ORDERS_PER_DAY
2018-02-01 | 1
2018-02-02 | 0
2018-02-03 | 1
...
2018-02-07 | 2
...
2018-03-02 | 1
...
2018-03-15 | 0
2018-03-16 | 0
Thanks for help!
You can simply use GROUP BY clause to do it.
SELECT `DATE`, COUNT(`PRODUCT_ID`) AS ORDERS_PER_DAY
FROM TABLE1
WHERE `DATE` BETWEEN '2018-02-01' AND CURDATE()
GROUP BY `DATE`
This query will result in filtering the records on your required date range and then grouping it by each day where there is data.
My syntax may not be exactly correct, but could you try something like this using the GROUP BY clause.
SELECT DATE, COUNT(*) AS ORDERS_PER_DAY
FROM TABLE1
GROUP BY DATE, PRODUCT_ID
HAVING PRODUCT_ID = '3'
you can read more about this here: https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html

MySQL order by date until a specific date, after it reverse order

Ok, so I have a table something like this
+----+-------+------------+
| id | title | date |
+----+-------+------------+
| 1 | aaa | 2018-08-13 |
| 2 | bbb | 2018-08-02 |
| 3 | ccc | 2018-07-06 |
| 4 | ddd | 2018-07-16 |
| 5 | fff | 2018-07-13 |
+----+-------+------------+
and I want to sort it by date column ascending, but only until a specific date, after that I want to sort it descending, like this
+----+-------+------------+
| id | title | date |
+----+-------+------------+
| 4 | ddd | 2018-07-16 |
| 2 | bbb | 2018-08-02 |
| 1 | aaa | 2018-08-13 |
| 5 | fff | 2018-07-13 |
| 3 | ccc | 2018-07-06 |
+----+-------+------------+
I thought I could use UNION, but either I don't know how to use it, or it doesn't accept ORDER BY clauses specified in each SELECT.
EDIT: I probably didn't explain myself so good. In my query I would need this to sort ascending by date all of the rows after a specific date (>= some date, in this case let's use 2018-07-15) and all of the rows before to be sorted descending.
You should do this with a single order by and no subquery:
order by (case when date >= #date then 1 else 0 end), -- put more recent first
(case when date >= #date then date end) asc, -- order the first group ascending
date desc -- order by second group descending
With reference to the groundwork laid down by D-Shih...
SELECT id
, title
, date
FROM
( SELECT *
, CASE WHEN date <'2018-07-15' THEN #i:=0 ELSE #i:=#i+1 END i
FROM t
, (SELECT #i:=0) vars
ORDER
BY date
) x
ORDER
BY i=0, i, date DESC;
http://sqlfiddle.com/#!9/58a8ac/20
You probably don't really need all the techniques shown above, but I'm just making this stuff up as I go along...
Try this union with subquery:
select * from
(select *,ord=0 from tablename where id=2
union
select *,ord=1 from tablename where id<>2)a
order by ord asc, date desc
#D-Shih has nearly got it right...
SELECT *
FROM yourtable
ORDER BY (CASE
WHEN `date`>"2018-07-06" THEN 'date'
ELSE DATE("2018-07-06")
) ASC,
`date` DESC;
You could do it with a UNION but this gets messy quickly.
You can also implement the CASE statement as LEAST()
Knowing exactly the dates you want to use, you could do it like this:
SELECT * FROM (
SELECT
concat(1,'-',#firstquery := #firstquery + 1) as rownum, table_name.*
FROM
table_name,
(SELECT #firstquery:=0) fq
WHERE
date_column <= '2018-08-05'
ORDER BY
date_column ASC) a
UNION ALL
SELECT * FROM (
SELECT
concat(2,'-',#secondquery := #secondquery + 1) as rownum, table_name.*
FROM
table_name,
(SELECT #secondquery:=0) sq
WHERE
date_column > '2018-08-05'
ORDER BY
date_column DESC) b
ORDER BY rownum ASC
It is quite big, but in this case I'm emulating the rownumber based on each subquery and concatenating that for ordering later. Meaning you could order backwards also at some point.
What I like about this one is that we have the order specified in the rownum based on each item ordered previous to the union.

Split date range and get combined results in mysql

I have two tables
orders_status_history
id | order_id | status | date
1 | 1201 | 2 | 2015-01-20
2 | 1124 | 4 | 2015-02-01
3 | 1245 | 1 | 2015-02-14
4 | 1365 | 2 | 2015-03-10
saved_shipping_invoices
id | order_id | product_id | date
1 | 1348 | 12541 | 2015-12-18
2 | 1298 | 11485 | 2016-01-02
3 | 1319 | 14521 | 2016-05-14
4 | 1441 | 10124 | 2016-05-14
and one year date range i.e.
$start_date = '2015-09-30';
$end_date = '2016-09-30';
Data in table "shipping_invoice_history" started from 2015-12-18. Now I want to break date interval on 2015-12-18. There will be two intervals now
$interval1_start = '2015-09-30';
$interval_end = '2015-12-17';
$interval2_start = '2015-12-18';
$interval2_end = '2016-09-30';
When it breaks the date interval, I want to get data from table "orders_status_history" on the first interval but on the second interval it gets data from "shipping_invoice_history" .Also I need to show the data in single table.
$week = '2015-09-30 ## 2016-09-30';
$week_ranges = explode('##', $week);
if ($week_ranges[0] > '2015-12-18' )
{
$invoices_shipped_qty = tep_db_query("SELECT * FROM `saved_shipping_invoices` WHERE `date_created` BETWEEN '".$week_ranges[0]."' AND '".$week_ranges[1]."'");
$invoices_shipped_arr = tep_db_fetch_array($invoices_shipped_qty);
$total_sent = $invoices_shipped_arr['shiped_qty'];
}
else {
$total_order_status_complete = tep_db_query("SELECT * FROM `orders_status_history` WHERE `orders_status_id` = '17' AND `date_added` BETWEEN '".$week_ranges[0]." 00:00:00' AND '".$week_ranges[1]." 23;59:59'");
$total_order_status_complete_arr = tep_db_fetch_array($total_order_status_complete);
Please suggest me how can i break date interval into two, get result from two tables and display in single run.
Probably this is what you want
select
'order_status_history' as table,
id,
order_id,
status,
null as product_id,
date from order_status_history
where
date between '2015-09-30' and '2015-12-17'
union all
select
'saved_shipping_invoices' as table,
id,
order_id,
null as status,
product_id,
date
from saved_shipping_invoices
where
date between '2015-12-18' and '2016-09-30'
Depending on how dynamic is your query, I like to do something like this instead of union.
I prefer this option:
select
if(date <='2015-12-17', 'Phase 1',
if(date >='2015-12-18', 'Phase 2',
'None')),
id,
order_id,
status,
null as product_id,
date from order_status_history
where
date between '2015-09-30' and '2016-09-30'
or
select
if(date between '2015-09-30' and '2015-12-17', 'Phase 1',
if(date between '2015-12-18' and '2016-09-30', 'Phase 2',
'None')),
id,
order_id,
status,
null as product_id,
date from order_status_history
where
date between '2015-09-30' and '2016-09-30'

SQL count Query retrieving 0

i want to list the amount of views per object_id, between the current date and the date year ago.
So, i have this Query:
SELECT count(*) FROM event_logs WHERE object_id=252 AND object_type='product' AND event_type='view' AND event_date BETWEEN 2014-02-14 AND 2015-02-14 GROUP BY month(event_date)
And the following table:
event_id | user_id | objectd_id | object_type | event_type | event_date
1 | 1 | 252 | product | view | 2014-02-25 00:00:00
2 | 1 | 252 | product | view | 2015-02-12 19:36:05
3 | 1 | 252 | product | view | 2015-01-05 19:36:05
The problem is when i execute the query, show an amount of results of 0 (zero),
Could have i been doing wrong?
Please help and thank you all for your attention!
One problem is the event_date constants:
SELECT count(*)
FROM event_logs
WHERE object_id = 252 AND
object_type = 'product' AND
event_type = 'view' AND
event_date BETWEEN 2014-02-14 AND 2015-02-14
------------------------^ ---------^---^----------^ missing quotes
GROUP BY month(event_date);
Date constants should be in single quotes. Otherwise, these are treated as arithmetic -- 2014 - 2 - 14 = 1998, which is not really a valid date.
Also, if you want the total value, it is unclear why you are grouping by the month. You can use CURRENT_DATE and date arithmetic and not have to hardcode the dates:
SELECT count(*)
FROM event_logs
WHERE object_id = 252 AND
object_type = 'product' AND
event_type = 'view' AND
event_date <= CURRENT_DATE and
event_date > date_sub(CURRENT_DATE, interval -1 year);
Depending on the exact logic, you might want to change the <= to < or whatever -- depending on whether you want to include the end dates. Note: if event_date has a time component, then you might want to use date(event_date) to strip it off.
Change to this
BETWEEN '2014-02-14 00:00:00' AND '2015-02-14 23:59:59'

Joining most recent column entry to MySQL query result

I have a PHP/MySQL based solution for displaying an ID and the number of entries that ID has on a MySQL database table in the past day, and year to date.
The information is simply output to a table.
We would also be able to quickly see the most recent value for a particular column associated with each ID on this same table.
The tables in use have the following descriptions:
TABLE: tags
id int auto_increment
Tag int(8)
Timestamp timestamp
Battery varchar(3) // Status for rfid tags battery condition
TABLE: tag_vehicle
id int auto_increment
Tag int(8)
VehicleId varchar(10)
And here is my MySQL query
SELECT tags.Tag,
sum(CASE WHEN year(Timestamp) = year(CURDATE()) then 1 else 0 end) as ytd,
sum(CASE WHEN date(Timestamp) = date(CURDATE()) then 1 else 0 end) as today,
tag_vehicle.VehicleId,
MAX(Timestamp) as latest
FROM tags
INNER JOIN tag_vehicle
ON tags.Tag = tag_vehicle.Tag
GROUP BY VehicleNumber;
This generates a table with these columns
| Tag | ytd | today | VehicleId | Timestamp |
|1234 | 300 | 12 | BUS1234 | 2014-09-22 |
I'm simply looking to add to my table the latest value of Battery that matches each Tag. I've been trying all morning to produce this result but I haven't had any luck.
| Tag | ytd | today | VehicleId | Timestamp | Battery |
|1234 | 300 | 12 | BUS1234 | 2014-09-22 | ok |
I'm not an expert on MySQL and its starting to feel like the query is too messy. I'm having a hard time figuring out how to get this battery value.
How should I go about obtaining the latest entry for Battery and matching it to the right row?
Is there some way to do it all in 1 (perhaps cleaner) query, or should I make 2 queries and match Battery columns to Tag columns?
You should be able to do this with the substring_index()/group_concat() trick:
SELECT t.tag,
sum(CASE WHEN year(Timestamp) = year(CURDATE()) then 1 else 0 end) as ytd,
sum(CASE WHEN date(Timestamp) = date(CURDATE()) then 1 else 0 end) as today,
tv.VehicleId,
MAX(Timestamp) as latest,
substring_index(group_concat(t.battery order by t.timestamp desc), ',', 1)
FROM tags t INNER JOIN
tag_vehicle tv
ON t.Tag = tv.Tag
GROUP BY VehicleNumber;
The tag column doesn't look right because it comes from an indeterminate row.

Categories