MYSQL displaying value in single record from multiple row - php

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

Related

subtraction within unions or joins in table php/mysql

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

Mysql query for highest vote perday

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.

how to query last image of 5 album by yii active record

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

MySQL query display problem

How can I display the users friends correctly on the users and friends side using my MySQL tables? My current code screws this up.
Users Friends Table
CREATE TABLE users_friends (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
user_id INT UNSIGNED UNSIGNED NOT NULL,
friend_id INT UNSIGNED NOT NULL,
friendship_status TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
date_created DATETIME NOT NULL,
PRIMARY KEY (id),
KEY user_id (user_id),
KEY friend_id (friend_id)
);
Users Table
CREATE TABLE users (
user_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
username VARCHAR(255) NULL,
avatar VARCHAR(255) NULL,
password CHAR(128) NOT NULL,
PRIMARY KEY (user_id),
UNIQUE KEY (username)
);
My Current MySQL Code
SELECT users.*, users_friends.*
FROM users
INNER JOIN users_friends ON users.user_id = users_friends.friend_id
WHERE (users_friends.user_id = '" . $user_id . "'
OR users_friends.friend_id = '" . $user_id . "')
AND users_friends.friendship_status = 1
GROUP BY users_friends.date_created
Try this query. This should give you all friends for a particular user based on your database relationship.
SELECT A.user_id, A.friend_id, B.username, B.avatar
FROM users_friends AS A
INNER JOIN users AS B
ON A.friend_id = B.user_id
AND A.user_id = #userToBeSearched
UNION
SELECT A.friend_id, A.user_id, B.username, B.avatar
FROM users_friends AS A
INNER JOIN users AS B
ON B.user_id = A.user_id
AND A.friend_id = #userToBeSearched
Note : I have removed the Group By clause for now because
I am afraid i do not quite understand your schema enough to make sense of why you would be grouping rows only by date_created
Adding the grouping clause will involve making another nested table as you will not be able to select columns not in the Group Clause.
Data used to test:-
Table : user
user_id |username| avatar | password
1 A AAAA
2 B BBBB
3 C CCCCC
4 D DDDDD
Table : user_friends
id | user_id | friend_id | friendship_status | date_created
1 1 2 1 Friday, October 22, 2010 3:09:44 PM
2 2 3 1 Friday, October 22, 2010 3:43:18 PM
3 2 4 1 Friday, October 22, 2010 3:43:26 PM

Search SQL Question Between Related Two Tables

I am writing some kind of search engine for my web application and i have a problem. I have 2 tables first of is projects table:
PROJECTS TABLE
id int(11) NO PRI NULL auto_increment
employer_id int(11) NO MUL NULL
project_title varchar(100) NO MUL NULL
project_description text NO NULL
project_budget int(11) NO NULL
project_allowedtime int(11) NO NULL
project_deadline datetime NO NULL
total_bids int(11) NO NULL
average_bid int(11) NO NULL
created datetime NO MUL NULL
active tinyint(1) NO MUL NULL
PROJECTS_SKILLS TABLE
project_id int(11) NO MUL NULL
skill_id int(11) NO MUL NULL
For example: I want ask this query to database:
1-) Skills are 5 and 7.
2-) Order results by created
3-) project title contains "php" word.
4-) Returned rows should contain projects.* columuns.
5-) Projects should be distinct(i don't want same projects in return of query).
Please write sql query that ensure these conditions. Thank You.
SELECT projects.*
FROM projects
WHERE EXISTS (
SELECT *
FROM projects_skills
WHERE skill_id = 5
AND project_id = projects.project_id
)
AND EXISTS (
SELECT *
FROM projects_skills
WHERE skill_id = 7
AND project_id = projects.project_id
)
AND project_title LIKE '%php%'
ORDER BY created
or
SELECT projects.*
FROM projects
WHERE EXISTS (
SELECT *
FROM projects_skills
WHERE skill_id IN (5, 7)
AND project_id = projects.project_id
)
AND project_title LIKE '%php%'
ORDER BY created
Depending on what your intended result is.
It sounds like you're looking for an EXISTS query, which verifies that matching rows exist in a table, but without performing a JOIN.
SELECT *
FROM projects
WHERE EXISTS (SELECT 1 FROM projects_skills AS ps WHERE ps.project_id = projects.project_id AND ps.skill_id IN (5, 7))
AND project_title LIKE '%php%'
ORDER BY created;

Categories