I have records of questions stored in database. One of the column in question is the ask_date.
Example stored in is: 1549923808.
I want to select records whose ask_date is within the current month.
Please how do I calculate that in the WHERE clause of my SQL ?
//Select questions with the heighest or Top votes or answers this month( current month)
$SQL = "SELECT * FROM(
SELECT Q.*,
(SELECT COUNT(Q.question_id) FROM $questions_table Q ) num_of_rows,
(SELECT COUNT(v.vote_id) FROM $votes_table v WHERE Q.question_id=v.ask_id AND v.vote_type=0 ) votes_down,
(SELECT COUNT(a.answer_id) FROM $answers_table a WHERE question_id=a.ask_id ) total_answers,
(SELECT COUNT(v.vote_id) FROM $votes_table v WHERE Q.question_id=v.ask_id ) votes_up,
CONCAT(m.firstname,' ',m.lastname) author_name,
m.username u_name FROM $questions_table Q
LEFT JOIN $main_table m ON Q.user_id=m.user_id
WHERE ............
) A LEFT JOIN $votes_table V ON A.question_id=V.ask_id
GROUP BY A.question_id ORDER BY (
SELECT COUNT(V.vote_id) vote
FROM $votes_table V
WHERE V.ask_id=A.question_id
) DESC LIMIT {$maxPageRecords} OFFSET {$offset}";
A simple way is:
where date_format(from_unixtime(ask_date), '%Y-%m') = date_format(now(), '%Y-%m')
However, that precludes the use of indexes. So, this might be better:
where ask_date >= unix_timestamp(date(concat_ws('-', year(now()), month(now()), 1)))) and
ask_date < unix_timestamp(date(concat_ws('-', year(now()), month(now()), 1))) + interval 1 month)
select records whose ask_date is within the current month :
This simple (and index-friendly) expression should get the job done :
WHERE ask_date >= UNIX_TIMESTAMP(DATE_FORMAT(NOW(), '%Y-%m-01'))
Using SQL Tuples:
WHERE (year(ask_date),month(ask_date)) = (year(now()),month(now()))
Related
I have a database with colums I am working on. What I am looking for is the date associated with the row where the SUM(#) reaches 6 in a query. The query I have now will give the date when the number in the colum is six but not the sum of the previous rows. example below
Date number
---- ------
6mar16 1
8mar16 4
10mar16 6
12mar16 2
I would like to get a query to get the 10mar16 date because on that date the number is now greater than 6. Earlier dates wont total up to six.
Here is an example of a query i have been working on:
SELECT max(date) FROM `numbers` WHERE `number` > 60
You could use this query, which tracks the accumulated sum and then returns the first one that meets the condition:
select date
from (select * from mytable order by date) as base,
(select #sum := 0) init
where (#sum := #sum + number) >= 6
limit 1
SQL Fiddle
Most databases support ANSI standard window functions. In this case, cumulative sum is your friend:
select t.*
from (select t.*, sum(number) over (order by date) as sumnumber
from t
) t
where sumnumber >= 10
order by sumnumber
fetch first 1 row only;
In MySQL, you need variables:
select t.*
from (select t.*, (#sumn := #sumn + number) as sumnumber
from t cross join (select #sumn) params
order by date
) t
where sumnumber >= 10
order by sumnumber
fetch first 1 row only;
Awesome!!!! It seems to be working great. Here is the code that I used.
SELECT date, id, crewname
FROM (select * FROM flightrecord WHERE `crewname` = 'brayn'
ORDER BY dutyTimeArrive DESC) as base,
(select #sum := 0) init
WHERE (#sum := #sum + tankDropCount) >= 6
limit 1
I am using this query for getting monthly record of employees those are present and absent.
However i am getting the result for one employee by using this query but for all employees it doesn't seems to work.
SELECT
m.emp_id AS `Empid`,
d.dt AS `AbsentDate`,
(CASE
WHEN p.punch_status IS NULL THEN 'A'
ELSE p.punch_status
END) s
FROM
(SELECT
DATE(t.added_date) AS dt
FROM
pmc_attendance t
WHERE
DATE(t.added_date) >= '2018-08-01'
AND DATE(t.added_date) < DATE_ADD('2018-08-31', INTERVAL 1 DAY)
GROUP BY DATE(t.added_date)
ORDER BY DATE(t.added_date)) d
CROSS JOIN
tbl_admin_users m
LEFT JOIN
pmc_attendance p ON DATE(p.added_date) >= d.dt
AND DATE(p.added_date) < d.dt + INTERVAL 1 DAY
AND p.emp_id = m.emp_id
WHERE
p.emp_id IS NULL AND m.emp_id = '000838'
GROUP BY d.dt
ORDER BY m.emp_id , d.dt
I am using two tables 1. tbl_admin_users- employee data stored 2. pmc_attendance- present records of employees.
in query if i have passed the and m.emp_id='000838' it works fines but i want to show all records for all employees. any suggestions how i can optimize this query.
There are a couple of ways to structure this query. I can see what yuo are doing, and I think the only issue is with your group by clauses. You dont need them as everything should be distinct. Your status will always be 'A' as you are only getting rows where there is no punch for the employee for the day, so you can also take out the case statement.
SELECT
m.emp_id AS Empid,
d.dt AS AbsentDate,
'A' s
FROM
(
SELECT distinct DATE(t.added_date) AS dt
FROM pmc_attendance t
WHERE t.added_date >= '2018-08-01' AND DATE(t.added_date) < DATE_ADD('2018-08-31', INTERVAL 1 DAY)
) d
CROSS JOIN tbl_admin_users m
LEFT JOIN pmc_attendance p ON p.emp_id = m.emp_id and DATE(p.added_date) >= d.dt AND DATE(p.added_date) < d.dt + INTERVAL 1 DAY
WHERE p.emp_id IS NULL
ORDER BY m.emp_id , d.dt
If you want to include both present and absent, you would need to put your case statement back in, and remove your check WHERE p.emp_id IS NULL
If you have multiple punchs for the day, then you need to resolve it down to a single entry with a MIN/MAX so you only get one row per person per day, and add back in your group by Emp_ID, d.dt
Am trying to find the min value from past 30 days, in my table there is one entry for every day, am using this query
SELECT MIN(low), date, low
FROM historical_data
WHERE name = 'bitcoin'
ORDER BY STR_TO_DATE(date,'%d-%m-%Y') DESC
LIMIT 7
But this value not returing the correct value. The structure of my table is
Table structure
And table data which is store is like this
Table data style
Now what i need is to get the minimum low value. But my query not working it give me wrong value which even did not exist in table as well.
Updates:
Here is my updated Table Structure.
enter image description here
And here is my data in this table which look like this
enter image description here
Now if you look at the data, i want to check the name of token omisego and fatch the low value from past 7 days which will be from 2017-12-25 to 2017-12-19
and in this cast the low value is 9.67, but my current query and the query suggested by my some member did not brings the right answer.
Update 2:
http://rextester.com/TDBSV28042
Here it is, basically i have more then 1400 coins and token historical data, which means that there will me more then 1400 entries for same date like 2017-12-25 but having different name, total i have more then 650000 records. so every date have many entries with different names.
To get the lowest row per group you could use following
SELECT a.*
FROM historical_data a
LEFT JOIN historical_data b ON a.name = b.name
AND a.low > b.low
WHERE b.name IS NULL
AND DATE(a.date) >= '2017-12-19' AND DATE(a.date) <= '2017-12-25'
AND a.name = 'omisego'
or
SELECT a.*
FROM historical_data a
JOIN (
SELECT name,MIN(low) low
FROM historical_data
GROUP BY name
) b USING(name,low)
WHERE DATE(a.date) >= '2017-12-19' AND DATE(a.date) <= '2017-12-25'
AND a.name = 'omisego'
DEMO
For last 30 day of 7 days or n days you could write above query as
SELECT a.*, DATE(a.`date`)
FROM historical_data2 a
LEFT JOIN historical_data2 b ON a.name = b.name
AND DATE(b.`date`) >= CURRENT_DATE() - INTERVAL 30 DAY
AND DATE(b.`date`) <= CURRENT_DATE()
AND a.low > b.low
WHERE b.name IS NULL
AND a.name = 'omisego'
AND DATE(a.`date`) >= CURRENT_DATE() - INTERVAL 30 DAY
AND DATE(a.`date`) <= CURRENT_DATE()
;
DEMO
But note it may return more than one records where low value is same, to choose 1 row among these you have specify another criteria to on different attribute
Consider grouping the same and running the clauses
SELECT name, date, MIN(low)
FROM historical_data
GROUP BY name
HAVING name = 'bitcoin'
AND STR_TO_DATE(date, '%M %d,%Y') > DATE_SUB(NOW(), INTERVAL 30 DAY);
Given the structure, the above query should get you your results.
// Try this code ..
SELECT MIN(`date`) AS date1,low
FROM historical_data
WHERE `date` BETWEEN now() - interval 1 month
AND now() ORDER by low ASC;
I have a table in my db, which contains following data:
————————————————————————————————————————————————————————————————————————
Id startDate availabilityStatus Hotel_Id
————————————————————————————————————————————————————————————————————————
1 2016-07-01 available 2
2 2016-07-02 available 2
3 2016-07-03 unavailable 2
4 2016-07-04 available 3
5 2016-07-05 available 3
6 2016-07-06 available 3
7 2016-07-07 unavailable 4
8 2016-07-08 available 4
9 2016-07-09 available 4
10 2016-07-10 available 4
Now, user wants to see all the Hotels which have 3 continuous days availability in July’16.
I am able to make the query to get the availability, but not sure how to fetch the Continuous date availability.
As per the above data, in July only Hotel Id 3, 4 have the continuous available dates, but as 2 also have the dates available. so how should we remove 2 and show just 3, 4 via MySQL query.
Please advise?
You can use the following query:
SELECT DISTINCT t1.hotel_id
FROM mytable AS t1
JOIN mytable AS t2
ON t1.hotel_id = t2.hotel_id AND
DATEDIFF(t1.startDate, t2.startDate) = 2 AND
t1.availabilityStatus = 'available' AND
t2.availabilityStatus = 'available'
LEFT JOIN mytable AS t3
ON t1.hotel_id = t3.hotel_id AND
t3.startDate < t2.startDate AND t3.startDate > t1.startDate AND
t3.availabilityStatus = 'unavailable'
WHERE t3.hotel_id IS NULL
The query is written in such a way, so that it can easily be adjusted in order to accommodate longer availability periods.
Edit:
Here's a solution using variables:
SELECT DISTINCT hotel_id
FROM (
SELECT hotel_id,
#seq := IF(#hid = hotel_id,
IF(availabilityStatus = 'available', #seq + 1, 0),
IF(#hid := hotel_id,
IF(availabilityStatus = 'available', 1, 0),
IF(availabilityStatus = 'available', 1, 0))) AS seq
FROM mytable
CROSS JOIN (SELECT #seq := 0, #hid := 0) AS vars
ORDER BY hotel_id, startDate) AS t
WHERE t.seq >= 3
You can test it with your actual data set and tell us how it compares with the first solution.
Try something like that. It works for any number of days. Replace N with 3.
SELECT DISTINCT A.Hotel_Id FROM table A
WHERE
A.availabilityStatus = 'available' AND
N-1 = (
SELECT count(DISTINCT startDate) FROM table B
WHERE B.availabilityStatus = 'available'
AND A.Hotel_Id = B.Hotel_Id
AND B.startDate
BETWEEN DATE_ADD(A.startDate, INTERVAL 1 DAY)
AND DATE_ADD(A.startDate, INTERVAL N-1 DAY)
)
It works like that: for each available date, count available dates in N-1 next days. If their count is N-1, add hotel_id to results.
Try this. I didn't get chance to test it as sqlfiddle is not working, but the general idea is to take 2 more instance of table by adding 1 and 2 days to the start date respectively.
Then join them based on derived dates and hotel id.
select t1.hotelid from
(select * from Table1 where availabilityStatus='available' ) t1
inner join
(select a.*, DATE_ADD(startDate,INTERVAL 1 DAY) as date_plus_one
from Table1 where availabilityStatus='available' ) t2
on t1.start_date=t2.date_plus_one and t1.hotelid=t2.hotelid
inner join
(select a.*, DATE_ADD(startDate,INTERVAL 2 DAY) as date_plus_two
from Table1 where availabilityStatus='available' ) t3
on t1.start_date=t3.date_plus_two and t1.hotelid=t3.hotelid
This query uses double self-join to find the same hotel available at day a, b and c, split by a day (function ADDDATE).
SELECT DISTINCT a.Hotel_Id
FROM table a
INNER JOIN table b ON a.Hotel_Id=b.Hotel_Id
INNER JOIN table c ON a.Hotel_Id=c.Hotel_Id
WHERE ADDDATE(a.startDate , INTERVAL 1 DAY) = b.startDate
AND ADDDATE(a.startDate , INTERVAL 2 DAY) = c.startDate
AND a.availabilityStatus = 'available'
AND b.availabilityStatus = 'available'
AND c.availabilityStatus = 'available'
Its working fine...
SELECT a.hotel_id FROM `mytable` as a WHERE
(select COUNT(id) from mytable as a1 where
DATE(a1.startDate)=DATE_ADD(a.startDate,INTERVAL 1 DAY) and
a1.hotel_id=a.hotel_id and
a1.availabilityStatus="Available"
) >0
and
(select COUNT(id) from mytable as a1 where
DATE(a1.startDate)=DATE_ADD(a.startDate,INTERVAL -1 DAY) and
a1.hotel_id=a.hotel_id and
a1.availabilityStatus="Available"
) >0
and
(select COUNT(id) from mytable as a1 where
DATE(a1.startDate)=DATE(a1.startDate) and
a1.hotel_id=a.hotel_id and
a1.availabilityStatus="Available"
) >0
This question already has answers here:
Calculate a running total in MySQL
(5 answers)
Closed 8 years ago.
I have a below query
SELECT COUNT( DISTINCT id ) AS `total` , YEAR( created_date ) AS `memberYear`
FROM `users` AS `u`
WHERE (
role_id =2
AND is_deleted =0
AND is_trashed =0
)
GROUP BY `memberYear`
With this query i am getting record like this
total memberYear
10 2012
12 2013
2 2014
Now i need to get record total sum with previous year
total memberYear sumTotal
10 2012 10
12 2013 22
2 2014 24
How can i get this sum of Total ? Any help will be appreciated.
Please have a try with this one:
SELECT COUNT( DISTINCT id ) AS `total` , YEAR( created_date ) AS `memberYear`,
#running_total := #running_total + COUNT(DISTINCT id) AS total
FROM `users` AS `u`
, (SELECT #running_total := 0) var_init_subquery
WHERE (
role_id =2
AND is_deleted =0
AND is_trashed =0
)
GROUP BY `memberYear`
You can only do that with mysql if you use a stored procedure, or use a nested select, but I would not recommend it. Since you use PHP, and already have the query response, just add the current year value to the previous one's :
$sumTotal=0;
while ($row=mysql_fetch_array($res)){
$sumTotal+=$row["total"];
}
You are looking for the cumulative sum. Unfortunately mysql does not yet support window functions which makes such things real easy. One way is to use a theta self join like:
SELECT X.memberYear, sum(y.total)
FROM (
SELECT COUNT( DISTINCT id ) AS `total` , YEAR( created_date ) AS `memberYear`
FROM `users` AS u
WHERE role_id =2
AND is_deleted =0
AND is_trashed =0
GROUP BY memberYear
) AS x
JOIN (
SELECT COUNT( DISTINCT id ) AS `total` , YEAR( created_date ) AS `memberYear`
FROM `users` AS `u`
WHERE role_id =2
AND is_deleted =0
AND is_trashed =0
GROUP BY `memberYear`
) y
on y.memberyear <= x.memberyear
group by X.memberYear
This is untested, so there might be some errors in there.