Merging MySQL Queries - mysql

I want to merge three queries and I want to get an aggregate result for these three queries, how can i achieve this in MySQL?
My queries
SELECT
order_table_no,
count(bill_no),
sum(finaldiscount)
from order_master
where `ORDER_TABLE_NO` like 'HOME%'
and order_time >= '2015-01-01'
and order_time <= '2015-01-20'
SELECT
distinct(ORDER_TABLE_NO),
sum(order_quantity*order_item_price) AS order_master_FINALDISCOUNT,
count(bill_no)
FROM `order_master` order_master
WHERE date(order_master.`ORDER_TIME`) >= '2015-01-01'
AND date(order_master.`ORDER_TIME`) <= '2015-01-20'
and order_table_no not like 'HOME%'
and order_table_no not like 'TAKE%'
GROUP BY ORDER_TABLE_NO
SELECT
order_table_no,
count(bill_no),
sum(finaldiscount)
from order_master
where `ORDER_TABLE_NO` like 'TAKE%'
and order_time >= '2015-01-01'
and order_time <= '2015-01-20'

It is a bit weird that your first and last query don't have any group by clauses. This doesn't require any joins - just use the MySQL IF Control Flow Function (http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#function_if):
select
order_table_no,
count(bill_no),
IF(order_table_no like 'TAKE%' or order_table_no like 'HOME%', sum(finaldiscount), sum(order_quantity * order_item_price)) finaldiscount
from
order_master
where
order_time >= '2015-01-01' and
order_time <= '2015-01-20'
group by
order_table_no

Related

Mysql select data between four dates rang

I have a problem with a sql query
Please see this screenshot
I want to select data from this two rangs.
Date from 1996-07-04 to 1996-07-08 (rang 1)
and also from 1996-07-15 to 1996-07-18 (rang 2)
this two rangs has multiple data on table but its return null.
Mysql sql query :
SELECT * FROM Orders where OrderDate >= '1996-07-04' and OrderDate <= '1996-07-08' and OrderDate >= '1996-07-15' and OrderDate <= '1996-07-18';
its return null.
I want to select data from this rangs.
It is because of the logical error Try using this:
SELECT * FROM Orders where
(OrderDate >= '1996-07-04' and OrderDate <= '1996-07-08')
or (OrderDate >= '1996-07-15' and OrderDate <= '1996-07-18');

condition in SELECT in mysql

I have a query that looks like this
SELECT customer, totalvolume
FROM orders
WHERE deliverydate BETWEEN '2020-01-01' AND CURDATE()
Is there any way to select totalvolume for specific date range and make it a separate column?
So for example, I already have totalvolume. I'd like to also add totalvolume for the previous month as a separate column (totalvolume where deliverydate BETWEEN '2020-08-01' AND '2020-08-31'). Is there a function for that?
Simply use 2 table copies:
SELECT t1.customer, t1.totalvolume, t2.totalvolume previousvolume
FROM orders t1
LEFT JOIN orders t2 ON t1.customer = t2.customer
AND t1.deliverydate = t2.deliverydate + INTERVAL 1 MONTH
WHERE t1.deliverydate BETWEEN '2020-08-01' AND '2020-08-31';
You can do it with case/when construct in your columns and just expand your WHERE clause. Sometimes I would do it by having a secondary #variables to simplify my clauses. Something like
SELECT
o.customer,
sum( case when o.deliveryDate < #beginOfMonth
then o.TotalVolume else 0 end ) PriorMonthVolume,
sum( case when o.deliveryDate >= #beginOfMonth
then o.TotalVolume else 0 end ) ThisMonthVolume,
sum( o.totalvolume ) TwoMonthsVolume
FROM
( select #myToday := date(curdate()),
#beginOfMonth := date_sub( #myToday, interval dayOfMonth( #myToday ) -1 day ),
#beginLastMonth := date_sub( #beginOfMonth, interval 1 month ) ) SqlVars,
orders o
WHERE
o.deliverydate >= #beginLastMonth
group by
o.customer
To start, the "from" clause of the query alias "SqlVars" will dynamically create 3 variables and return a single row for that set. With no JOIN condition, is always a 1:1 ratio for everything in the orders table. Nice thing, you don't have to pre-declare variables and the #variables are available for the query.
By querying for all records on or after the beginning of the LAST month, you get all records for both months in question. The sum( case/when ) can now use those variables as the demarcation point for the respective volume totals.
I know you mentioned this was a simplified query, but masking that might not be a perfect answer to what you need, but may help you look at it from a different querying perspective.

MySQL Subquery with datetime comparison from main query values

I am trying to do what seems like a simple query.. I have a query which works fine until I try to add a subquery to the select clause. I am trying to add a column by querying a second table with the dates I get from the first. I don't know if a join might be better. If you look at my first sample it returns every record in my second table instead of using the date range from the outer select statement.
SELECT `sales`.`date` as 'newdate', `sales`.`material`,
`customer_logs`.`name`, `sales`.`billingqty` ,
(select count(*) from iis_logs where datetime > (select
Date_add(date_format(newdate, "%Y-%m-%d 00:00:00"), interval - 1 day))
and datetime < date_format(newdate, '%Y-%m-%d 00:00:00' and url like
CONCAT('%',material,'%') limit 1) as tr
FROM `sales`
JOIN `customer_logs` ON `customer_logs`.`customer_number` =
`sales`.`soldtopt`
WHERE `date` >= '2017-09-01'
AND `date` <= '2017-09-30'
ORDER BY `date` DESC
LIMIT 10;
If I just type the string as a date in like this it returns within a second:
SELECT `sales`.`date` as 'newdate', `sales`.`material`,
`customer_logs`.`name`, `sales`.`billingqty` ,
(select count(*) from iis_logs where datetime > '2017-09-01 00:00:00'
and datetime < '2017-09-03 00:00:00' and url like
CONCAT('%',material,'%') limit 1) as tr
FROM `sales`
JOIN `customer_logs` ON `customer_logs`.`customer_number` =
`sales`.`soldtopt`
WHERE `date` >= '2017-09-01'
AND `date` <= '2017-09-30'
ORDER BY `date` DESC
LIMIT 10;
It is not taking the value of newdate I am trying to get in select statement, instead it is returning every row in iis_logs table...
This looks like a perfect candidate for a join. FWIW, mysql query optimizer typically does better on joins that subqueries anyway.

Reverse order for GROUP BY in MySQL

I need to select first value for every hour from my db. But I don't know how to reverse order on GROUP BY statement.
How can i rewrite my query (now it selects last value in hour)?
SELECT HOUR(`time`) as hour, mytable.*
FROM mytable
WHERE DATE(`time`) ="2015-09-12" GROUP BY HOUR(`time`) ORDER BY `time` ASC;
This query gave me expected result:
SELECT HOUR(`time`) as hour, sortedTable.* FROM
(SELECT electrolysis.* FROM electrolysis
WHERE DATE(`time`)='2015-09-12' ORDER BY `time`) as sortedTable
GROUP BY HOUR(`time`);
You can just select the MIN HOUR in sub query , try using the query:
SELECT * from mytable WHERE `time` IN (
SELECT MIN(HOUR(`time`)) as `hour`
FROM mytable
WHERE DATE(`time`) ="2015-09-12"
GROUP BY HOUR(`time`) ) ORDER BY `time` ASC;
You can do something like this:-
SELECT sub0.min_time,
mytable.*
FROM mytable
INNER JOIN
(
SELECT MIN(`time`) AS min_time
FROM mytable
GROUP BY HOUR(`time`)
) sub0
ON mytable.`time` = sub0.min_time
WHERE DATE(`time`) ="2015-09-12"
ORDER BY `time` ASC
This is using a sub query to get the smallest time in each hour. This is then joined back against your main table on this min time to get the record that has this time.
Note that there is a potential problem here if there are multiple records that share the same time as the smallest one for an hour. There are ways around this, but that will depend on your data (eg, if you have a unique id field which is always ascending with time then you could select the min id for each hour and join based on that)
You can use below query, which is more optimized just make sure that time field should be indexed.
SELECT HOUR(m.time), m.*
FROM mytable AS m
JOIN
(
SELECT MIN(`time`) AS tm
FROM mytable
WHERE `time` >= '2015-09-12 00:00:00' AND `time` <= '2015-09-12 23:59:59'
GROUP BY HOUR(`time`)
) AS a ON m.time=a.tm
GROUP BY HOUR(m.time)
ORDER BY m.time;

Select the first element in each day of the month

How to select the first element of each day in a month with mysql query ?
I have table with offers - startdate, so i can check for each day,month,year i'm getting the element but, i'm wondering how to get only the first element in each day of some month ?
Assume the following
Table is called mytable
Table has id as primary key
Table has dt as datatime
You want the first id of everyday in February 2012
Try this:
SELECT B.id FROM
(
SELECT DATE(dt) date_dt,MIN(dt) dt
FROM mytable
WHERE dt >= '2012-02-01 00:00:00'
AND dt < '2012-03-01 00:00:00'
GROUP BY DATE(dt)
) A
LEFT JOIN mytable B USING (dt);
If any dt has multiple B.id values try this:
SELECT dt,MIN(id) id
(
SELECT B.id,B.dt FROM
(
SELECT DATE(dt) date_dt,MIN(dt) dt
FROM mytable
WHERE dt >= '2012-02-01 00:00:00'
AND dt < '2012-03-01 00:00:00'
GROUP BY DATE(dt)
) A
LEFT JOIN mytable B USING (dt)
) AA GROUP BY dt;
Assuming startdate is a DATETIME type, and the earliest entry is the one with the earliest DATETIME value, for March, 2012:
SELECT DISTINCT *
FROM tbl t1
LEFT JOIN tbl t2
ON (t2.startdate BETWEEN '2012-02-01 00:00:00' AND '2012-02-29 23:59:59')
AND t2.startdate < t1.startdate
WHERE (t1.startdate BETWEEN '2012-02-01 00:00:00' AND '2012-02-29 23:59:59')
AND t2.startdate IS NULL
If there are no duplicate dates, then you don't need the DISTINCT.
This query works by joining with any earlier record for the same month, so if nothing was joined, it's the earliest, through process of elimination.
This technique is explained in detail in the book SQL Antipatterns.
This could also be solved with subqueries, but this type of JOIN is supposed to be easier to optimize by MySQL than subqueries, which often negate the use of indexes.
without knowing the exact structure of your table something like this should work:
SELECT MIN(offerId) FROM offers WHERE startdate <= '2012-03-06' AND startdate >= '2012-02-06' GROUP BY date(startdate)
It sounds like you are trying to do something like the following:
SELECT col_1, date_col, col_3 FROM tbl
WHERE
date_col = ( SELECT min(date_col) FROM tbl
WHERE
year(date_col) = 2006 AND
month(date_col) = 02
);
This can also be used to find the max( date_col ) . Hope this helps.
Just to offer a different way to skin this cat (much easier in SQL Server for once actually)
SELECT
t0.offerId
FROM
offers AS t0 LEFT JOIN
offers AS t1 ON t0.offerId = t1.offerId AND t1.startDate > t0.startDate AND
(t0.startDate BETWEEN '2012-02-01' AND '2012-03-01') AND
(t1.startDate BETWEEN '2012-02-01' AND '2012-03-01')
WHERE
t1.col1 IS NULL;
If you have multiple rows with the same exact time you will get multiple values returned, which you can weed out in your application logic or with a sub-query. BTW this is called a groupwise minimum/maximum.