I need to find intersection between the following queries in MYSQL
SELECT *
FROM project.backup_table
where project.backup_table.date <= (SELECT date FROM project.main_inout_table ORDER BY date desc LIMIT 1)
and project.backup_table.date >= (SELECT date FROM project.main_inout_table ORDER BY date asc LIMIT 1)
SELECT *
FROM project.backup_table
WHERE concat(empid,date) not IN (SELECT concat(empid,date) FROM project.main_inout_table
The tables are:
maintable
backuptable
My atttempt:
SELECT * FROM project.backup_table
where project.backup_table.date <= (SELECT date FROM project.main_inout_table
ORDER BY date desc LIMIT 1) and project.backup_table.date >= (SELECT date FROM project.main_inout_table
ORDER BY date asc LIMIT 1) and exists (SELECT * FROM project.backup_table
WHERE concat(empid,date) not IN (SELECT concat(empid,date)
FROM project.main_inout_table));
Problem: the details of tid 4 is present shouldn't it be filter out by second select query ?
The intersection would be the rows that meet both conditions. So, just bring the conditions together:
SELECT bt.*
FROM project.backup_table bt
WHERE bt.date <= (SELECT MAX(date) FROM project.main_inout_table mit) AND
bt.date >= (SELECT MIN(date) FROM project.main_inout_table mit) AND
NOT EXISTS (SELECT 1
FROM project.main_inout_table mit
WHERE mit.empid = bt.empid AND mit.date = bt.date
);
Note the following changes:
The tables are given aliases, which are abbreviations for the table names.
The columns are all qualified with the table aliases.
The first two subqueries simply use MIN() and MAX(). These could be combined into one subquery or join, but this follows your original formulation.
The last subquery uses EXISTS rather than CONCAT(). Actually, this could also use IN with tuples (something that MySQL supports, but not all databases).
Related
Is it possible to order when the data comes from many select and union it together? Such as
In this statement, the vouchers data is not showing in the same sequence as I saved on the database, I also tried it with "ORDER BY v_payments.payment_id ASC" but won't be worked
( SELECT order_id as id, order_date as date, ... , time FROM orders WHERE client_code = '$searchId' AND order_status = 1 AND order_date BETWEEN '$start_date' AND '$end_date' ORDER BY time)
UNION
( SELECT vouchers.voucher_id as id, vouchers.payment_date as date, v_payments.account_name as name, ac_balance as oldBalance, v_payments.debit as debitAmount, v_payments.description as descriptions,
vouchers.v_no as v_no, vouchers.v_type as v_type, v_payments.credit as creditAmount, time, zero as tax, zero as freightAmount FROM vouchers INNER JOIN v_payments
ON vouchers.voucher_id = v_payments.voucher_id WHERE v_payments.client_code = '$searchId' AND voucher_status = 1 AND vouchers.payment_date BETWEEN '$start_date' AND '$end_date' ORDER BY v_payments.payment_id ASC , time )
UNION
( SELECT return_id as id, return_date as date, ... , time FROM w_return WHERE client_code = '$searchId' AND w_return_status = 1 AND return_date BETWEEN '$start_date' AND '$end_date' ORDER BY time)
Wrap the sub-select queries in the union within a SELECT
SELECT id, name
FROM
(
SELECT id, name FROM fruits
UNION
SELECT id, name FROM vegetables
)
foods
ORDER BY name
If you want the order to only apply to one of the sub-selects, use parentheses as you are doing.
Note that depending on your DB, the syntax may differ here. And if that's the case, you may get better help by specifying what DB server (MySQL, SQL Server, etc.) you are using and any error messages that result.
You need to put the ORDER BY at the end of the statement i.e. you are ordering the final resultset after union-ing the 3 intermediate resultsets
To use an ORDER BY or LIMIT clause to sort or limit the entire UNION result, parenthesize the individual SELECT statements and place the ORDER BY or LIMIT after the last one. See link below:
ORDER BY and LIMIT in Unions
(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;
I have this table from which I have to select the latest row on the basis of date and time column for each checkpost
I have tried the following queries but not returning the latest data for each checkpost.
SELECT checkpost_id,current_rate,date,time FROM revisionrates
WHERE date IN (SELECT max(date) FROM revisionrates GROUP BY checkpost_id)
The expected output is
You can use window functions:
select rr.*
from (select rr.*,
row_number() over (partition by checkpost_id order by date desc, time desc) as seqnum
from revisionrates rr
) rr
where seqnum = 1;
This requires MySQL 8.0. In earlier versions of MySQL, this is a bit trickier, but one method uses tuples
select rr.*
from rr
where (date, time) in (select rr2.date, rr2.time
from revisionrates rr2
where rr2.checkpoint_id = rr.checkpoint_id
order by rr2.date desc, rr2.time desc
limit 1
);
I'm using an union statement in mysql but i've some problems sorting the results. The ORDER statement doesn't works at all, the results comes out always sorted by the id field.
Here an example query:
SELECT a.* FROM ( ( select * from ticket_ticket AS t1 WHERE ticket_active=1 ORDER BY t1.ticket_date_last_modified DESC )
UNION ( select * from ticket_ticket AS t2 WHERE ticket_active=0 ORDER BY t2.ticket_date_last_modified DESC, t2.ticket_status_id DESC ) )
AS a LIMIT 0,20;
I want to order the results of the first SELECT by last_modified time, and the second SELECT by time and status. But the ORDER statement get just skipped. The results always come out ordered by the ticket_id ( the PRIMARY KEY ).
What's wrong in this query ?
Thanks!
Ok, i've fixed it writing the query this way:
SELECT a.*
FROM
(SELECT *
FROM ticket_ticket
WHERE ticket_active=1
ORDER BY ticket_date_last_modified DESC) AS a
UNION ALL
SELECT b.*
FROM
(SELECT *
FROM ticket_ticket
WHERE ticket_active=0
ORDER BY ticket_date_last_modified DESC, ticket_status_id DESC) AS b LIMIT 0,
20;
You are using a UNION query that will return distinct values, and the order of the returned rows is not guaranteed.
But you don't need an union query for this:
select *
from ticket_ticket AS t1
ORDER BY
ticket_active!=1,
ticket_date_last_modified DESC,
ticket_status_id DESC
LIMIT 0,20;
I have a query with an order
ORDER BY FIND_IN_SET(status, '1,5,3,4,2'), end_date ASC
but what I would like is any record with status 1 to be ordered end_date ASC and any status 2 ordered by end_date DESC and the others ordered by end_date ASC.
Can this be done? Thanks
Try this query -
SELECT * FROM table_name
ORDER BY
IF(status < 2, status, 3),
IF(status = 2, TO_DAYS(end_date) * -1, TO_DAYS(end_date))
Refining Devart's answer...
SELECT * FROM table_name
ORDER BY find_in_set(status, '1,5,3,4,2')
CASE
WHEN (status = 2) then TO_DAYS(end_date) * -1
ELSE TO_DAYS(end_date)
END
Use 2 queries to get your different sorts, then get the UNION of the queries.
SELECT * FROM (
(SELECT * FROM table WHERE status!=2
ORDER BY FIND_IN_SET(status, '1,5,3,4'), end_date ASC)
UNION
(SELECT * FROM table WHERE status=2 ORDER BY end_date DESC)
) AS table_sort ORDER BY FIND_IN_SET(status, '1,5,3,4,2')
Since you want the status 2 records last, technically you wouldn't need to SELECT on the UNION and ORDER it, but I added that in case you wanted a different sort order.
I have table contains around 14 million records, and I have multiple SP's contain Dynamic SQL, and these SP's contain multiple parameters,and I build Indexes on my table, but the problem is I have a performance Issue, I tried to get the Query from Dynamic SQL and run it, but this query takes between 30 Seconds to 1 minute, my query contains just select from table and some queries contain join with another table with numeric values in where statement and grouping and order by.
I checked status result, I found the grouping by takes all time, and I checked Explain result, It's using right index.
So what I should doing to enhance my queries performance.
Thanks for your cooperation.
-- EDIT, Added queries directly into question instead of comment.
SELECT
CONCAT(column1, ' - ', column1 + INTERVAL 1 MONTH) AS DateRange,
cast(SUM(column2) as SIGNED) AS Alias1
FROM
Table1
INNER JOIN Table2 DD
ON Table1.Date = Table2.Date
WHERE
Table1.ID = 1
AND (Date BETWEEN 20110101 AND 20110201)
GROUP BY
MONTH(column1)
ORDER BY
Alias1 ASC
LIMIT 0, 10;
and this one:
SELECT
cast(column1 as char(30)) AS DateRange,
cast(SUM(column2) as SIGNED)
FROM
Table1
INNER JOIN Table2 DD
ON Table1.Date = Table2.Date
WHERE
Table1.ID = 1
AND (Date BETWEEN 20110101 AND 20110102)
GROUP BY
column1
ORDER BY
Alias1 ASC
LIMIT 0, 10;
For this query:
SELECT
CONCAT(column1, ' - ', column1 + INTERVAL 1 MONTH) AS DateRange <<--error? never mind
, cast(SUM(column2) as SIGNED)
FROM Table1
INNER JOIN Table2 DD ON Table1.Date = Table2.Date
WHERE Table1.ID = 1
AND (Date BETWEEN 20110101 AND 20110201)
GROUP BY MONTH(column1) <<-- problem 1.
ORDER BY column2 ASC <<-- problem 2.
LIMIT 0, 10;
If you group by a function MySQL cannot use an index. You can speed this up by adding an extra column YearMonth to the table1 that contains the year+month, put an index on that and then group by yearmonth.
The order by does not make sense. You are adding column2, ordering by that column serves no purpose. If you order by yearmonth asc the query will run much faster and make more sense.