MySQL - query records above date and one below - mysql

In my MySQL database I have records with date of inserting (as one of column of datetime type).
Besides of some where clause constraints I want to select all records above given date (from given date to now) and exactly one record closest below given date.
Any ideas how to achieve this using MySQL in efficient way?
I thought about using count and rank, but I think it can be very inefficient.

Maybe someting like this?
(SELECT * FROM mytable WHERE mydate >= xxx)
UNION
(SELECT * FROM mytable WHERE mydate < xxx ORDER BY mydate DESC LIMIT 1)

Related

Generalize a sql query to accomodate full and incremental extract

I have a the following query :
select * from table where createddate>='03-Feb-2020' and createddate<'04-Feb-2020'
The above query will give me incremental count for a single day.
How do i generalize the above query so that i can get the entire historical data/full dump without changing the where clause.
For example:
select * from table where createddate>='VARIABLE1' and createddate<'VARIABLE2'
Is there a way that without changing the schema of the sql query i can just pass in different values for the createddate to get the full dump?
Is this what you want?
where createddate >= '1000-01-01' and createddate < '9999-12-31'
Note that dates in MySQL must be formated as YYYY-MM-DD.
Do you want group by?
select date(createddate), count(*)
from table
group by date(createddate);
This returns the count for each day.

How to count the same date values per day

I'm completly begginer but and don't even know what type this query is.
BTW. I want to get count Date(MYdatetime) type values per day by join the same table.
Is there any question comparing this query?
I have query like that:
select
date_format(
adddate('2011-1-1', #num:=#num+1),
'%Y-%m-%d'
) date
from
any_table,
(select #num:=-1) num
limit
365
In MySQL, I would simply do:
select date(t.datecol), count(*)
from any_table t
group by date(t.datecol);
If you want data for a particular time span, use a where clause:
select date(t.datecol), count(*)
from any_table t
where t.datecol >= '2011-01-01' and t.datecol < '2012-01-01'
group by date(t.datecol);
Use GROUP BY:
SELECT
year(theDate),
month(theDate),
day(theDate),
count(*)
FROM
test_table
GROUP BY
year(theDate),
month(theDate),
day(theDate)
You are wanting a count of all dates in a given time frame, including those dates that are not in the table (and thus would have a count of 0). This is a bit of a headache but not unprecedented. You basically need to create a utility table that is just every date you could possibly want and then do an outer join against that table. So create a simple table like:
CREATE TABLE `all_dates` (
`the_date` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And populate it with all dates you think you could potentially need. I think a 10 year radius from the current year would be good. So fill it with every date between 2008-01-01 and 2028-12-31.
INSERT INTO all_dates
(the_date) VALUES
('2008-01-01'),
('2008-01-02'),
('2008-01-03')
There is probably a clever way to generate all rows in one query using a procedure or somesuch, but I don't know what it would be, so I would personally just create a simple script (like in PHP) to generate those rows.
Once the all_dates table has all the date value rows for your needs, you can then do a query to get the count of each date (including missing dates) like:
SELECT DATE(all_dates.the_date), COUNT(any_table.datecol)
FROM any_table
RIGHT JOIN all_dates ON DATE(any_table.datecol) = all_dates.the_date
GROUP BY all_dates.the_date
HAVING all_dates.the_date BETWEEN '2011-01-01' AND '2012-01-01'

Applying dual conditions in case when in MYSQL

(question edited) My table has id,status,date,sequence
Situation: Get ids which satisfies:
date is max, not more than today's and status is A
if more than 1 status' with same date then get id only if it has max sequence
I am writing MYSQL in dbVisulizer.
edit: trying with query:
select id, max(date), max(sequence) from
table
where
table.date<=now() and status='A'
order by date desc,sequence desc
It sounds like I am just asking direct question without trying anything by myself, but for this situation I am completely stuck, I tried with case when but couldn't really accomplish any good, any starting point would be appriciated.
select id, max(date), max(sequence) from
table
where
table.date<=now() and status='A'
order by date desc,sequence desc
group_by id;
This should give you the desired results. Adapt table and field names to your table and fields.
select id from
table
where
table.date<now() and table.status='A'
order by date desc,sequence desc
limit 1;
You should check it for mistakes by yourself.

Order By on date field starting in a middle point of the dates range

I have a table "A" with a "date" field. I want to make a select query and order the rows with previous dates in a descending order, and then, the rows with next dates in ascending order, all in the same query. Is it possible?
For example, table "A":
id date
---------------------
a march-20
b march-21
c march-22
d march-23
e march-24
I'd like to get, having as a starting date "march-22", this result:
id date
---------------------
c march-22
b march-21
a march-20
d march-23
e march-24
In one query, because I'm doing it with two of them and it's slow, because the only difference is the sorting, and the joins I have to do are a bit "heavy".
Thanks a lot.
You could use something like this -
SELECT *
FROM test
ORDER BY IF(
date <= '2012-03-22',
DATEDIFF('2000-01-01', date),
DATEDIFF(date, '2000-01-01')
);
Here is a link to a test on SQL Fiddle - http://sqlfiddle.com/#!2/31a3f/13
That's wrong, sorry :(
From documentation:
However, use of ORDER BY for individual SELECT statements implies nothing about the order in which the rows appear in the final result because UNION by default produces an unordered set of rows. Therefore, the use of ORDER BY in this context is typically in conjunction with LIMIT, so that it is used to determine the subset of the selected rows to retrieve for the SELECT, even though it does not necessarily affect the order of those rows in the final UNION result. If ORDER BY appears without LIMIT in a SELECT, it is optimized away because it will have no effect anyway.
This should do the trick. I'm not 100% sure about adding an order in a UNION...
SELECT * FROM A where date <= now() ORDER BY date DESC
UNION SELECT * FROM A where date > now() ORDER BY date ASC
I think the real question here is how to do the joining once. Create a temporary table with the result of joining, and make the 2 selects from that table. So it will be be time consuming only on creation (once) not on select query (twice).
CREATE TABLE tmp SELECT ... JOIN -- do the heavy duty here
With this you can make the two select statenets as you originally did.

Two date columns, one date. How can I get the data?

I have the following problem:
In mysql I have a table which contains two date columns start_date and end_date. The date format is yyyy-mm-dd. What I am trying to do is to get all data from all the rows where a specific date, lets say '2012-03-05' mateches one of these date columns or are something in between.
How can I create a good sql-query that gets the data needed? I've checked on the between statement but I don't really know if that's the best way to go. I guess this is generally a simple task but I just can't figure a good query out.
Thanks.
SELECT * FROM table WHERE start_date <= '2012-02-29' AND end_date >= '2012-02-29';
Should do it.
This is a very common way to structure your tables with ranges of dates, especially in temporal database designs. It lets you perform range-based queries very efficiently, assuming that indexes on both columns exist. You query the data like this:
select *
from mytable t
where t.start_date <= #desired_date and t.endDate > #desired_date
#desired_date is the date for which you would like to query, e.g. '2012-03-05'.
Note the <= on one side and > on the other side, without =. This is done to ensure that the from-to ranges define non-overlapping intervals.
Not sure, try something like this:
SELECT
*
FROM
mytable
WHERE
'2012-03-05' BETWEEN start_date AND end_date
SELECT * FROM mytable
WHERE '2012-03-05' BETWEEN start_date AND end_date;