I have a following db table review_vote
review_id | user_id | status | date_added
2 3 good 20130116135259
3 3 normal 20130116145259
4 2 normal 20130116155259
5 2 good 20130116165259
6 2 good 20130116175259
7 1 great 20130116185259
8 3 good 20130117135259
9 3 normal 20130117145259
currently I can get the highest vote by using the following query:
SELECT review_id FROM review_vote GROUP BY review_id HAVING COUNT(*) =
(
SELECT MAX(x.counts) FROM
(
SELECT review_id, COUNT(*) counts FROM review_vote GROUP BY review_id
)x
)
order by date_added desc
but if i need to get highest vote perday how can i modified the code above? Which means if today were 2013-01-16 I need to get highest vote for yesterday 2013-01-15
my attempt to use date_added = CURDATE() is failed.
SQLFIDDLE: http://sqlfiddle.com/#!2/9a2b5/6
Update query:
CREATE TABLE IF NOT EXISTS `review_vote` (
`review_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`status` varchar(100) NOT NULL,
`date_added` varchar(100) NOT NULL,
KEY `review_id` (`review_id`,`user_id`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `review_vote` (`review_id`, `user_id`, `status`, `date_added`) VALUES
(223, 2, 'lame', '20130116195259');
INSERT INTO `review_vote` (`review_id`, `user_id`, `status`, `date_added`) VALUES(222, 2, 'lame', '20130115195259');
Just add this in your where condition:
DATE_FORMAT(date_added, '%Y-%m-%d') = CURDATE()
Updating as per your error
SELECT review_id FROM review_vote AS RV WHERE DATE_FORMAT(RV.date_added, '%Y-%m-%d') = CURDATE()
GROUP BY review_id HAVING COUNT() =
(
SELECT MAX(x.counts) FROM
(
SELECT review_id, COUNT() counts FROM review_vote GROUP BY review_id
)x
)
Please have a look at demo :demo
SELECT review_id
FROM review_vote
WHERE date_added LIKE '20130115%'
GROUP BY review_id
ORDER BY COUNT(*) DESC
LIMIT 1
But really you ought to consider changing your date_added column to an appropriate temporal type, like DATETIME or TIMESTAMP.
Add the following to your WHERE clause:
`date_added` BETWEEN
DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 DAY), '%Y%m%d')
AND DATE_FORMAT(CURDATE(), '%Y%m%d')
Make sure you have an index on date_added!
Documentation for the date functions is all here: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
Life would be easier for you if your date_added column was a native date type.
Related
first of all this is my first time posting a question here. If my question is already asked and answered, please provide me with the links to that question because even i don't know how to properly ask this.
so i have a table with records like this.
ID ITEM_ID DATE OUT IN
1 1002 2019-01-20 1 NULL
2 1002 2019-01-22 NULL 2
3 1004 2019-01-23 4 NULL
4 1007 2019-01-23 4 NULL
5 1002 2019-01-24 1 NULL
6 1004 2019-01-26 NULL 13
7 1003 2019-02-03 NULL 35
how can i select it to look it like this in mysql?
ITEM_ID DATE_OUT OUT DATE_IN IN
1002 2019-01-24 1 2019-01-22 2
1003 - - 2019-02-03 35
1004 2019-01-23 4 2019-01-26 13
1007 2019-01-23 4 - -
what i'm trying to do is more like concate from multiple row of same ITEM ID into 1 latest date of IN and latest date of OUT in 1 row
edit : i've add more data set for more clarification of what i'm trying to achieve.
thank you very much to anyone that have been helping me.
SELECT
a.item_id,
b.date AS date_out,
b.out,
a.date AS date_in,
a.in
FROM (SELECT item_id, date, in FROM your_table WHERE in IS NOT NULL) a
INNER JOIN (SELECT item_id, date, out FROM your_table WHERE out IS NOT NULL) b
ON b.item_id= a.item_id
Yoy can try with a left Join
SELECT a.id,a.item_id,b.date as date_out,`b.out` as 'out',a.date_in as date_in,`a.in` as 'in'
from table1 a left join table1 b
on item_id=item_id and `a.in` is not null and `b.out` is not null
If the table is called dta, then this would be:
SELECT dta_out.ID,dta_in.ITEM_ID,dta_out.`DATE` DATE_OUT, dta_out.`OUT`, dta_in.`DATE` DATE_IN, dta_in.`IN` FROM dta dta_in
INNER JOIN dta dta_out
ON dta_in.ITEM_ID=dta_out.ITEM_ID
WHERE NOT dta_in.`IN` IS NULL AND NOT dta_out.`OUT` IS NULL
I used the following table create:
CREATE TABLE `dta` (
`ID` int(11) DEFAULT NULL,
`ITEM_ID` int(11) DEFAULT NULL,
`DATE` date DEFAULT NULL,
`OUT` int(11) DEFAULT NULL,
`IN` int(11) DEFAULT NULL
)
first of all you have your table created wrong, make it like this
CREATE TABLE `your_database_name`.`new_table_name` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`item_id` INT(10) NULL,
`date_in` DATETIME NULL,
`date_out` DATETIME NULL,
`out` INT(10) NULL,
`in` INT(10) NULL,
PRIMARY KEY (`id`));
you should store the dates separately so you can select them more easy, and the query to show what you want is:
SELECT id, item_id, date_out, out, date_in, in from new_table_name;
To select the date you want from your table is going like this:
SELECT ID, ITEM_ID, (SELECT DATE FROM table_name WHERE OUT IS NOT NULL) AS
DATE_OUT, OUT, (SELECT DATE FROM table_name WHERE IN IS NOT NULL) AS DATE_IN, IN
from table_name
this select above is on your specific table with your specific 2 rows, please create the table as i posted at the begining of answer, that will make your life easier(i gave you the select aswell)
You can use this query to fetch the desired result:
SELECT DISTINCT
item_id,
(SELECT max(`date`) FROM items WHERE `out` = 1 AND item_id = 1002) DATE_OUT,
MAX(`OUT`) `OUT`,
(SELECT max(`date`) FROM items WHERE `IN` = 2 AND item_id = 1002) DATE_IN,
MAX(`IN`) `IN`
FROM items
Here is the SQL fiddle
SQL Query
Let's jump right into my problem and imagine that we have this simple table
CREATE TABLE `test` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`score` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `test` (`id`, `score`)
VALUES
(1, 10),
(2, 15),
(3, 6),
(4, 17);
What I want to do is the following. I want to sort by score and then, get the rank of the field with the ID 3
Since the entry with the ID 3 has the lowest score it would be rank 4.
I have this query, to get the ranks sorted by score
SELECT #rownum:=#rownum+1 rank, id, score from test t, (SELECT #rownum:=0) r ORDER BY score DESC;
The result is the following
rank || id || score
1 4 17
2 2 15
3 1 10
4 3 6
However, what I want to achieve is to get the rank instantly. Without having the ranks and results of the other values. I can't just add a WHERE CLAUSE with the condition that the ID should be 3, because If I do so the rank is always 1 because the query only matches one entry in the database.
How would I get the rank directly without iterating somehow over the result?
Why not just count how many are better than the id you want the rank of?
For example for id 3:
SELECT count(*)+1 FROM test where score > (SELECT score from test WHERE id = 3))
Just change the id at the end of the subquery to get the rank of another id
Add a index to score column and use below query-
select count(*) from test a join test b on a.score > b.score where a.id =3
i have an income and expense table. i want to select them both in a single query and get the difference between the income.amount field and expense.amount field grouping by month. so that the query will return a result whereby the total of expenses amount from the total of income amount basing the calculation on month. i used used two methods but non worked. find the below:
SELECT *, count(*), sum(`transaction`.amount) as tiamount, sum(expenditure.amount) as teamount, monthname(`transaction`.date) as mni, monthname(expenditure.date) as mne
FROM `transaction`, expenditure
WHERE month(expenditure.`date`)=month(`transaction`.`date`) and month(`transaction`.`date`)=month(expenditure.`date`)
GROUP BY monthname(`transaction`.date) ORDER BY `transaction`.date Desc
the other is :
SELECT count(*), `transaction`.date, sum(`transaction`.amount) as tiamount, sum(`transaction`.amount - expenditure.amount) as diff, monthname(`transaction`.date) as mni
FROM `transaction` left join expenditure on monthname(`transaction`.date) = monthname(expenditure.date)
UNION ALL
SELECT count(*), expenditure.date, sum(expenditure.amount) as teamount, sum(`transaction`.amount - expenditure.amount) as diff, monthname(expenditure.date) as mne
FROM expenditure left join `transaction` on monthname(`transaction`.date) = monthname(expenditure.date)
any help would be appreciated. Thanks.
ok thanks all. i solved the issue. each time the page is loaded, it checks to see if the table balance2 already exist, if it does it is dropped and recreated on the fly
mysql_query($query_truncate = "drop table IF EXISTS balance2");
$create= "CREATE TABLE balance2 (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT ,
`count` VARCHAR( 50 ) NOT NULL DEFAULT '',
`month` VARCHAR( 50 ) NOT NULL DEFAULT '',
`amount` VARCHAR( 50 ) NOT NULL DEFAULT '',
`amount2` VARCHAR( 20 ) NOT NULL ,
`type` VARCHAR( 20 ) NOT NULL ,
`date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = latin1";
mysql_query($create);
Then in used the INSERT INTO...SELECT...UNION SELECT....
to select from the expenses and income table to insert into the newly created balance table.
query_merge = "INSERT INTO balance2 (count, date, amount, amount2, month, type)
(SELECT count(*), t.date, sum(t.amount),0 ,monthname(t.date), 'income'
FROM `transaction` as t group by month(t.date))
UNION
(SELECT count(*), e.date, 0,sum(e.amount) as teamount, monthname(e.date) as mne, 'expense'
FROM expenditure as e group by month(e.date))";
this worked perfectly as it gave me all the results i wanted.
Thought it might help someone else. see ya
I use Yii framework to develop a website, I want to know how to get the last 5 images orderd by create_time but not within the same album by using Yii active record and by plain SQL.
here's my albums table:
CREATE TABLE IF NOT EXISTS `tbl_album` (
`album_id` int(11) NOT NULL AUTO_INCREMENT,
`album_name` varchar(45) DEFAULT NULL,
`album_folder_name` int(11) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`create_user_id` int(11) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`update_user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`album_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=55 ;
and here's my images table:
CREATE TABLE IF NOT EXISTS `tbl_image` (
`image_id` int(11) NOT NULL AUTO_INCREMENT,
`image_name` varchar(100) DEFAULT NULL,
`image_description` varchar(100) DEFAULT NULL,
`image_album_id` int(11) NOT NULL,
`create_time` datetime DEFAULT NULL,
`create_user_id` int(11) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`update_user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`image_id`),
KEY `fk_image_album` (`image_album_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;
please note that I use "create_time" for sorting images.
Again, I need a query to get the last 5 images orderd by create_time but not within the same album by Yii active record and plain SQL.
for example the last 7 images are:
a.jpg in the album 7
b.jpg in the album 5
c.jpg in the album 7
d.jpg in the album 6
e.jpg in the album 3
f.jpg in the album 4
g.jpg in the album 2
h.jpg in the album 1
I need the query result to be like the following:
a.jpg in album 7
b.jpg in album 5
d.jpg in album 6
e.jpg in album 3
f.jpg in album 4
not like the following:
a.jpg in album 7
b.jpg in album 5
c.jpg in album 7
d.jpg in album 6
e.jpg in album 3
Thanks in advance.
Try this:
SELECT
a.album_name,
i1.image_name
FROM tbl_album a
INNER JOIN tbl_image i1 ON i1.image_album_id = a.album_id
INNER JOIN
(
SELECT image_album_id, MIN(image_id) image_id
FROM tbl_image
GROUP BY image_album_id
) i2 ON i2.image_album_id = i1.image_album_id
AND i1.image_id = i2.image_id
ORDER BY a.album_name DESC
LIMIT 5;
The JOIN with:
SELECT image_album_id, MIN(image_id) image_id
FROM tbl_image
GROUP BY image_album_id
will insure that for each album, the first image will be returned. Therefore you will got only one image for each album, then LIMIT 5 will limit the result set to be only 5 albums.
SQL Fiddle Demo
Note that: The ORDER BY clause will determine which five albums will be returned by the LIMIT 5 clause. So don't expect that the albums are returned in the way they are stored as the expected result in your question, because records in the table has no specific order. They are stored as a set, and you have to specify an ORDER BY clause in your query to get them in a specific order.
Update: IF you are looking for the last created image for each album, use the MAX(creaet_time) instead like so:
SELECT
a.album_name,
i1.image_name,
date_format(i1.create_time, '%Y-%m-%d') create_time
FROM tbl_album a
INNER JOIN tbl_image i1 ON i1.image_album_id = a.album_id
INNER JOIN
(
SELECT image_album_id, MAX(create_time) LatestCreateTime
FROM tbl_image
GROUP BY image_album_id
) i2 ON i2.image_album_id = i1.image_album_id
AND i1.create_time = i2.LatestCreateTime
ORDER BY i1.create_time DESC
LIMIT 5;
Updated SQL Fiddle Demo
Update 2: For the duplicate values, use the DISTINCT keyword, or you can use the MAX(image_id) instead, since the image_id is autoincremental, like so:
SELECT
a.album_name,
i1.image_name,
date_format(i1.create_time, '%Y-%m-%d') create_time
FROM tbl_album a
INNER JOIN tbl_image i1 ON i1.image_album_id = a.album_id
INNER JOIN
(
SELECT image_album_id, MAX(image_id) LatestId
FROM tbl_image
GROUP BY image_album_id
) i2 ON i2.image_album_id = i1.image_album_id
AND i1.image_id = i2.LatestId
ORDER BY i1.create_time DESC
LIMIT 5;
Updated SQL Fiddle Demo
I find another solution to my question!
SELECT *
FROM tbl_image
WHERE image_id IN (SELECT MAX(image_id)
FROM tbl_image
GROUP BY image_album_id)
ORDER BY create_time DESC
LIMIT 5;
It gives me the same result, Without use inner join which reduce performance,
What your opinion about this solution?
SQL Fiddle
Try this and let me know what it returns,
select m.image_name,a.album_name
from tbl_album a inner join
tbl_image m on a.album_id=m.image_id
group by m.image_name,a.album_name
order by 2 LIMIT 5
Say I have the following table:
CREATE TABLE `table` (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
userid INT UNSIGNED NOT NULL,
reference INT,
`datetime` DATETIME
) Engine=InnoDB;
I want to select from the table, group by the reference and order by DATE, but also order by the latest reference entry?
For example:
reference: 79
datetime: 2011-12-31 00:32:30
reference: 77
datetime: 2011-12-31 00:40:30
reference: 77
datetime: 2011-12-31 00:43:30
reference: 77
datetime: 2011-12-31 00:45:30
reference: 78
datetime: 2011-12-31 00:47:30
They should show in this order: 78, 77 (the 00:45 one), 79
I currently have this as my query:
SELECT *
FROM `table`
WHERE `userid` = '" . mysql_real_escape_string($id) . "'
GROUP BY `reference`
ORDER BY `datetime` DESC
How can I get this query to work? So when a reference which already exists gets another entry, it jumps to the top of the list?
Thank you
Try
SELECT id, userid, reference, MAX(datetime) AS datetime
FROM `table` WHERE `userid` = ID
GROUP BY `reference`
ORDER BY `datetime` DESC
you need to specify all the columns near Group By clause.
SELECT id, userid, reference, MAX(datetime) AS datetime
FROM `table` WHERE `userid` = ID
GROUP BY `id`, `userid`, `reference`
ORDER BY `datetime` DESC