Double SQL Query - JOIN - php

I need a double SELECT sql query from 2 different tables with names visits & items
1.: SELECT visitid, visitdate, visitreason FROM visits WHERE personid = 10
2.: SELECT itemid, itemname, itemtime FROM items WHERE itemvisitid= visitid
I think I need to do a JOIN but don’t know exactly how.
Table examples:
Table: visits
visitid | personid | visitdate | visitreason
1 | 10 | 05/07/2014 | no reason
2 | 10 | 06/07/2014 | some reason
3 | 12 | 06/07/2014 | no reason
4 | 10 | 12/07/2014 | some other reason
Table: items
itemid | personid | itemvisitid | itemname | itemtime
1 | 10 | 2 | box | 23
2 | 10 | 2 | clock | 70
3 | 10 | null | water | 50
4 | 10 | null | paper | 40
5 | 12 | 3 | box | 26
What I have now is this:
$query = "SELECT visitid, visitdate, visitreason FROM visits WHERE personid = '10' ORDER BY visitdate DESC";
// 2nd select: "SELECT itemid, itemname, itemtime FROM items WHERE itemvisitid= visitid";
$db->setQuery($query);
$results = $db->query();
while($row = mysqli_fetch_array($results)){
echo "<tr>
<td>".$row['visitid'].", ".$row['visitdate']."</td>
<td>".$row['visitreason']."</td>
<td>".$row['itemid'].",".$row['itemname'].", ".$row['itemtime']."</td>
</tr>";
}
I need results to be something like this:
<tr>
<td>1, 05/07/2014</td><td>no reason</td><td></td>
<td>2, 06/07/2014</td><td>some reason</td><td>1, box, 23<br />2, clock, 70</td>
<td>4, 12/07/2014</td><td>some other reason</td><td></td>
</tr>

I guess your might to use GROUP_CONCAT like this:
DEMO: http://sqlfiddle.com/#!2/9d4e22/15
SELECT visitid, DATE_FORMAT(visitdate,'%m/%d/%Y'), visitreason,
GROUP_CONCAT(itemid,itemname, itemtime)
FROM visits left join items on visits.visitid = items.itemvisitid
WHERE visits.personid = 10
GROUP BY visitid, visitdate, visitreason
You might want to read this to know GROUP_CONCAT :
How to use GROUP_CONCAT in a CONCAT in MySQL
The document of GROUP_CONCAT() is here:
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
hope this helps.

SELECT `visits`.`visitid`, `visits`.`visitdate`, `visits`.`visitreason`,`items`.`itemname`, `items`.`itemtime` from `visits` INNER JOIN `items` ON `visits`.`personid`=`items`.`personid` WHERE `visits`.`personid` = '10' ORDER BY `visits`.`visitdate` DESC
if there is any error please change the field name personid in 'items' table.and then check.

This query:
SELECT v.visitid,
v.visitdate,
v.visitreason,
i.itemid,
i.itemname,
i.itemtime
FROM visits v
INNER JOIN items i
ON ( v.visitid = i.itemvisitid )
WHERE v.person_id = 10
ORDER BY v.visitdate DESC,
i.itemid ASC
will link both tables and produce a resultset that you can traverse using a double loop. The outer loop to process changes to the visit, and the inner to add every item visited in a particular visit.

Related

How to count row by using GROUP mysql bind_param?

How to count row by using GROUP mysql bind_param ?
Table : check
.
__________________________
| id | product_id | user |
| 1 | 123 | test |
| 2 | 456 | test |
| 3 | 456 | test |
| 4 | 123 | test |
| 5 | 789 | test |
and this is my code
<?PHP
$username = "test";
$sql = 'SELECT COUNT(*) FROM check WHERE user = ? GROUP BY product_id';
$statement = $db_mysqli->prepare($sql);
$statement->bind_param('s', $username);
$statement->execute();
$result = $statement->get_result();
$row = $result->fetch_row();
$all_product = $row[0];
echo $all_product;
?>
When I test code it's show 5 I want to know how can I do for show 3 group by product_id
You need to change your SQL query.
SELECT COUNT(DISTINCT PRODUCT_ID) FROM check WHERE user = ?
this will produce a result of 3
If you wanted one row for each product, then you would do this:
SELECT product_id, COUNT(*) AS c FROM check WHERE user = ? GROUP BY product_id
which would look like this:
| product_id | c |
| 123 | 2 |
| 456 | 2 |
| 789 | 1 |
Try this query.
$statement=$mysqli->prepare("SELECT user,COUNT(*) FROM check GROUP BY product_id");
I hope it will help you.
you can use one of these three queries as per your need. It will give you results as shown below.
To get the total of rows with distinct product_id present in table-:
SELECT COUNT(DISTINCT product_id) FROM check;
Result-:
COUNT(DISTINCT product_id)
3
To get the rows with distinct product_id row-:
SELECT COUNT(DISTINCT product_id) FROM check GROUP BY product_id;
Result-:
COUNT(DISTINCT product_id)
1
1
1
To get the row with distinct product_id with the count number of duplicate product_id present in the table -:
SELECT COUNT(product_id) FROM check GROUP BY product_id
Result-:
COUNT(product_id)
2
2
1

How to do a result and row that will find the sql sum of two columns?

Table 1 Table 2
_________________ ____________________
| ID| Name |Age | | ID| Cost | Date |
|---|-------|----| |---|-------|-------|
| 1 | Kirk | 33 | | 1 | 10 | 9/10 |
| 2 | Lonzo | 55 | | 1 | 20 | 7/8 |
| 3 | Dave | 44 | | 2 | 12 | 25/7 |
| 3 | 5 | 30/4 |
| 3 | 5 | 4/10 |
I want the result to be Kirk, who is 33, has a total cost of 30 and total dates to 2
etc.. (btw they enter their names and all this comes up)
The sql statement would be like this?
$sql= "SELECT Table1.Name, Table1.ID, Table2.ID, Table1.Age, SUM(Table2.Cost), SUM(Table2.Date)
AS count from Table1, Table2
WHERE Table1.ID = Table2.ID and Table1.Name = (my example here)"
$result = $conn->query($sql);
$Cost = 0;
$Date= 0;
$rec = $result->fetch_assoc();
$Date= $rec{'count'};
$Cost= $rec{'count'};
$Age = $rec{'Age'}
echo "$Name, who is $Age years old a total cost of $Cost and $Date total dates";
Im getting errors, saying my variables are undifined
so how would I put them into variables?
EDIT fixed
instead of using the sql to find it, i used result from a while loop that kept adding one to another variable (to count the date). The cost is able to do in both sql(sum) and result.
instead of using the sql to find it, i used result from a while loop that kept adding one to another variable (to count the date). The cost is able to do in both sql(sum) and result.
You were missing a group clause. I also put that in a subquery and used an INNER JOIN
SELECT Id, Name, Age, Cost, Dates
FROM Table1
INNER JOIN (
SELECT Id i, SUM(Cost) Cost,
COUNT(Date) Dates
from Table2
GROUP BY Id) t
ON i=Id
WHERE Name = 'Kirk'
You should also change one of the php statements to
$Cost= $rec{'Cost'};
Just use join..
SELECT table2.date ,SUM(cost) AS tatol FROM table1
JOIN table2 ON table2.id = table1.id
WHERE table1.id = 1

How do I get distinct rows by a column?

I have a huge number of rows that I'd like to get say, last 5 records inserted in that database from 10 different users. If the same user inserted the last 3 rows into database, we must get one row, skip the others two and move to get a row per user, until it count up to 5.
A database like that:
user_id | news_id | title
1 | 1 | foo-1
2 | 2 | foo-2
3 | 3 | foo-3
1 | 4 | baa
4 | 5 | baa0
5 | 6 | baa1
5 | 7 | baa2
6 | 8 | baa3
7 | 9 | baa4
Should return:
user_id | news_id | title
1 | 1 | foo-1
2 | 2 | foo-2
3 | 3 | foo-3
4 | 5 | baa0
5 | 6 | baa1
The current filter was done by PHP, like this:
$used = array();
while ($data = mysql_fetch_array($query)) {
$uid = $data['user_id'];
if(in_array($uid, $used))
continue;
array_push($used, $uid);
// do something with data
}
But I want to refactor it, and do the filter purely by mysql, if possible. I don't know much MySql and that's why I'm having problem to archive this...
Here's what I've tried
select DISTINCT(user_id), news_id, title from XXX
WHERE GROUP BY (news_id) DESC
LIMIT 0,5
How can I do that?
1 way you can do it is to generate a partitioned row number per user and then select 5 records where RowNumber = 1.
SELECT *
FROM
(
SELECT
d.user_id
,d.news_id
,d.title
,(#rn:= if(#uid = user_id, #rn + 1,
if(#uid:=user_id,1,1)
)
) as RowNumber
FROM
Data d
CROSS JOIN (SELECT #uid:=-1, #rn:=0) vars
ORDER BY
user_id
,news_id
) t
WHERE
t.RowNumber = 1
ORDER BY news_id
LIMIT 5;
http://rextester.com/JRIZI7402 - example to show it working
Note you can change the row order by simply changing the ORDER BY statement of the derived table so if you have a column that will signify the latest record e.g. an identity column or a datetime column you can use that, but user_id must be the first criteria to be partitioned correctly.
Do it from your query.
"SELECT * FROM table GROUP BY user_id ORDER BY news_id DESC LIMIT 5"
well, i think this will achieve what you are after.
select user_id, news_id, title from tableName
GROUP BY user_id
ORDER BY news_id DESC
LIMIT 0,5
Hope this helps!

Select columns from multiple tables where a column in each table is equal to a variable

I have 2 tables:
items
| item_id | item_added_by_user_id | item_name |
| -------- | ------------------------- | ---------- |
| 1 | 23 | item 1 |
| 2 | 23 | item 2 |
| 3 | 24 | item 3 |
extra_access
| item_id | extra_user_id |
| -------- | --------------- |
| 1 | 25 |
| 2 | 26 |
| 3 | 28 |
I want to check whether the current logged in user has access to edit this item. Users who have access are users under item_added_by_user_id and users under extra_user_id with the same item_id.
I read up on JOINs and came up with this:
$sql = "SELECT items.item_added_by_user_id, ea.extra_user_id FROM items
INNER JOIN extra_access AS ea
ON items.item_id = ea.item_id AND
items.item_added_by_user_id=" . $SESSION['user_id'];
My 'logic' was that if any rows are returned, the user must have access, but this doesn't work.
What can I do to check whether the logged in user has access?
SELECT COUNT(*)
FROM items
WHERE item_added_by_user_id=$SESSION['user_id']
OR item_id IN(
SELECT item_id
FROM extra_access
WHERE extra_user_id=$SESSION['user_id']
)
AND item_id=$idItem;
Try this:
$sql = "SELECT items.item_added_by_user_id, ea.extra_user_id FROM items
INNER JOIN extra_access AS ea
ON items.item_id = ea.item_id
WHERE
items.item_added_by_user_id=" . $SESSION['user_id']
. " OR ea.extra_user_id=" . $SESSION['user_id'];
From your description, I think a union all query is appropriate:
select i.item_id
from items i
where item_added_by_user_id = $SESSION_USER
union all
select ea.item_id
from extra_access ea
where extra_user_id = $SESSION_USER;
My answer is quite the same than #Fuujin, but I only added the $idItem because in your question you mention "I want to check whether the current logged in user has access to edit this item" :
$sql = "SELECT distinct items.items_id
FROM items
LEFT JOIN extra_access AS ea ON items.item_id = ea.item_id
WHERE items.items_id = ".$idItem."
AND (items.item_added_by_user_id = ".$_SESSION['user_id']." OR ea.extra_user_id = ".$_SESSION['user_id'].")";
Moreover, I use LEFT join, not INNER, which could be a problem if items has no entry in extra_access.
If there is at least 1 result, then user has rights.

SELECT same row as repeated result from mysql DB

I have a table like
+------+----------+
| id | location |
+------+----------+
| 1 | TVM |
| 2 | KLM |
| 3 | EKM |
+------+----------+
And I have an array of id like [1,2,1,3,1]. I need to get the result as
+------+----------+
| id | location |
+------+----------+
| 1 | TVM |
| 2 | KLM |
| 1 | TVM |
| 3 | EKM |
| 1 | TVM |
+------+----------+
I am already tried WHERE IN like conditions but no luck.
A where statement cannot multiply the number of rows. It can only filter rows out. You want a join:
select tl.*
from tablelike tl join
(select 1 as n union all select 2 union all select 1 union all
select 3 union all select 1
) n
on tl.id = n.n;
Note: if you are already generating the list via a query or from a table, then use that for the query rather than passing the list out of the database and then back in.
You could also return this result with a query like this; this uses a separate SELECT to return each occurrence of row with id=1.
( SELECT id, location FROM mytable WHERE id IN (1,2)
ORDER BY id
)
UNION ALL
( SELECT id, location FROM mytable WHERE id IN (1,3)
ORDER BY id
)
UNION ALL
( SELECT id, location FROM mytable WHERE id IN (1)
ORDER BY id
)
Following a similar pattern, the result could be obtained by combining the results from five SELECT statements, each returning a separate row. That would probably be a little simpler to achieve from a small array, e.g.
$glue = ") ) UNION ALL
(SELECT id, location FROM mytable WHERE id IN (";
$sql = "(SELECT id, location FROM mytable WHERE id IN ("
. implode($glue, $myarray)
. ") )";

Categories