I need to return data from two tables this way
Array(
[0] => Array(
[Name] => lorem,
[Qty] => 2),
[1] => Array(
[Name] => ipsum,
[Qty] => 1),
[2] => Array(
[Name] => dolor,
[Qty] => 0)
)
PHP will only take care of getting the data, there will be no manipulation to organize it.
Two tables, one to record a certain event, the date and the id of a table related to the event. And the tables are like this:
tableA
id | date | tableB_id
1 2020-10-02 2
1 2020-10-19 2
1 2020-10-21 1
1 2020-11-2 3
1 2020-11-11 1
tableB
id | name
1 lorem
2 ipsum
3 dolor
And my SQL query
SELECT b.name as Name, a.created_at as created
FROM tableA b
INNER JOIN tableA a ON b.tableA_id = a.id WHERE MONTH(b.created_at) = '10' ORDER BY a.id;
which results in
Name | created
ipsum 2020-10-02
ipsum 2020-10-19
lorem 2020-10-21
You can Left Join TableA, but it irst need to have all the wanted rows as a subquery, to get also the 0 count
CREATE TABLE tableA (
`id` int,
`date` date,
`tableB_id` int
);
INSERT INTO tableA
(`id`, `date`, `tableB_id`)
VALUES
('1', '2020-10-02' , '2'),
('1' , '2020-10-19' , '2'),
('1' , '2020-10-21' , '1'),
('1' , '2020-11-02' , '3'),
('1' , '2020-11-11', '1');
CREATE TABLE tableB (
`id` int,
`name` varchar(19)
);
INSERT INTO tableB
(`id`, `name`)
VALUES
('1', 'lorem'),
('2', 'ipsum'),
('3', 'dolor');
SELECT b.`name`, Count(`tableB_id`)
FROM tableB b LEFT JOIN (SELECT * FROM tableA WHERE MONTH(`date`) = '10') a ON a.tableB_id = b.id
GROUP BY b.name
;
name | Count(`tableB_id`)
:---- | -----------------:
lorem | 1
ipsum | 2
dolor | 0
db<>fiddle here
You can use next php code:
$query = "SELECT
name Name, COUNT(tableA.id) Qty
FROM tableB
LEFT JOIN tableA ON tableB.id = tableA.tableB_id AND MONTH(tableA.date) = 10
GROUP BY tableB.name;";
// get DB version using PDO
$stmt = $pdo->prepare($query);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($rows);
Live PHP fiddle
Result:
Array
(
[0] => Array
(
[Name] => dolor
[Qty] => 0
)
[1] => Array
(
[Name] => ipsum
[Qty] => 2
)
[2] => Array
(
[Name] => lorem
[Qty] => 1
)
)
Related
I have two tables which I'm trying to run a query on.
If I run the below query in phpmyadmin I get the results I expect, just one result returned with id 9, but when running it on my webpage, its returning all 4 results. I can put what ever I want as the user id, even one that doesn't exist, its ignoring it.
$sql = "
SELECT c.*
, cu.userID
FROM ConversationUsers AS cu
LEFT
JOIN Conversations AS c
ON c.id = cu.convoID
WHERE cu.userID = userID
";
$q = $pdo->prepare($sql);
$q->bindValue(':userID', $vars['userID']);
$q->execute();
if($q->errorCode() != 0) {
$errors = $q->errorInfo();
echo($errors[2]);
}
foreach ($q->fetchAll() as $row) {
$convos[] = $row;
}
echo "<pre>";
print_r($convos);
echo "</pre>";
echo "
SELECT c.*
, cu.userID
FROM ConversationUsers AS cu
LEFT
JOIN Conversations AS c
ON c.id = cu.convoID
WHERE cu.userID = " . $vars["userID"];
The echo produces:
SELECT c.*
, cu.userID
FROM ConversationUsers AS cu
LEFT
JOIN Conversations AS c
ON c.id = cu.convoID
WHERE cu.userID = 1
The print produces
Array
(
[0] => Array
(
[id] => 9
[0] => 9
[lastUpdated] => 2019-12-29 00:00:00
[1] => 2019-12-29 00:00:00
[userID] => 1
[2] => 1
)
[1] => Array
(
[id] => 9
[0] => 9
[lastUpdated] => 2019-12-29 00:00:00
[1] => 2019-12-29 00:00:00
[userID] => 2
[2] => 2
)
[2] => Array
(
[id] => 10
[0] => 10
[lastUpdated] => 2019-12-29 00:00:00
[1] => 2019-12-29 00:00:00
[userID] => 2
[2] => 2
)
[3] => Array
(
[id] => 10
[0] => 10
[lastUpdated] => 2019-12-29 00:00:00
[1] => 2019-12-29 00:00:00
[userID] => 3
[2] => 3
)
)
The tables are setup as follows
CREATE TABLE `Conversations` (
`id` int(11) NOT NULL,
`lastUpdated` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `Conversations` (`id`, `lastUpdated`) VALUES
(9, '2019-12-29 00:00:00'),
(10, '2019-12-29 00:00:00');
CREATE TABLE `ConversationUsers` (
`convoID` int(11) NOT NULL,
`userID` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `ConversationUsers` (`convoID`, `userID`) VALUES
(9, 1),
(9, 2),
(10, 2),
(10, 3);
You're missing the : in :userID. That makes the WHERE always be true:
$sql = "SELECT c.*, cu.userID FROM ConversationUsers AS cu LEFT JOIN Conversations AS c ON c.id = cu.convoID WHERE cu.userID = :userID";
Your echo line used $vars["userID"] which is why it showed the correct result.
You miss the : before the parameter in your query:
$sql = "SELECT c.*, cu.userID FROM ConversationUsers AS cu LEFT JOIN Conversations AS c ON c.id = cu.convoID
WHERE cu.userID = :userID";
I have two table like this:
Product
id | title
-------------------------------
1 | Skirt
2 | Pants
Product_thumbnail
id | product_id | image
-------------------------------
1 | 1 | pant.jpg
2 | 1 | shoes.png
When I want to get product with the thumbnail, I query like this:
SELECT p.*, pt.image FROM product p
LEFT JOIN product_thumbnail pt ON pt.product_id = p.id;
The output I expected
[0]=> [
[id] => 1
[image] =>
[
[0] => pant.jpg
[1] => shoes.jpg
]
]
[1]=> [
[id] => 2
[image] => null
]
But the real output
[0]=> [
id => 1
image => pant.jpg
]
[1]=> [
id => 1
image => shoes.jpg
]
[2]=> [
id => 2
image => shoes.jpg
]
As you see, there is 2 element duplicate, so I need to merge it by hand, is there any way to achieve this more easy? Because my table have many tables relate together more than this, I'm using PHP, I use array_merge_recursive() to merge them but if do like that I get duplicate value in each field, like this:
[0]=> [
[id] =>
[
[0] => 1
[1] => 1
]
[image] =>
[
[0] => pant.jpg
[1] => shoes.jpg
]
]
It's not what I want, can anyone give me an idea?
Consider the following. The code could I'm sure be written more economically, but hopefully you get the idea...
<?php
/*
DROP TABLE IF EXISTS product;
CREATE TABLE product
(id SERIAL PRIMARY KEY
,title VARCHAR(12) NOT NULL UNIQUE
);
INSERT INTO product VALUES
(1,'Hat'),
(2,'Shoe');
DROP TABLE IF EXISTS product_thumbnail;
CREATE TABLE product_thumbnail
(id SERIAL PRIMARY KEY
,product_id INT NOT NULL
,image VARCHAR(12) NOT NULL UNIQUE
);
INSERT INTO product_thumbnail VALUES
(1,1,'sombrero.jpg'),
(2,1,'stetson.png');
SELECT p.id
, p.title
, t.image
FROM product p
LEFT
JOIN product_thumbnail t
ON t.product_id = p.id;
+----+-------+--------------+
| id | title | image |
+----+-------+--------------+
| 1 | Hat | sombrero.jpg |
| 1 | Hat | stetson.png |
| 2 | Shoe | NULL |
+----+-------+--------------+
*/
require('path/to/connection/stateme.nts');
$query = "
SELECT p.id
, p.title
, t.image
FROM product p
LEFT
JOIN product_thumbnail t
ON t.product_id = p.id;
";
$result = mysqli_query($db,$query);
$old_array = array();
while($row = mysqli_fetch_assoc($result)){
$old_array[] = $row;
}
$new_array = array();
foreach ($old_array as $row) {
$new_array[$row['id']]['title'] = $row['title'];
$new_array[$row['id']]['image'][] = $row['image'];
}
$new_array = array_values($new_array); // reindex
print_r($new_array);
?>
Outputs
Array
(
[0] => Array
(
[title] => Hat
[image] => Array
(
[0] => sombrero.jpg
[1] => stetson.png
)
)
[1] => Array
(
[title] => Shoe
[image] => Array
(
[0] =>
)
)
)
MySQL doesn't support arrays, but you can aggregate the data into a string:
SELECT p.*, GROUP_CONCAT(pt.image) as images
FROM product p LEFT JOIN
product_thumbnail pt
ON pt.product_id = p.id
GROUP BY p.id;
Note that aggregating only by the id and selecting p.* is allowed and even standard SQL -- assuming that id is a primary key or declared to be unique. This is the one situation when this syntax is permitted.
I have two tables:
table1:
id email
1 john#gmail.com
2 doe#gmail.com
table2:
userid key value
1 firstname john
1 phone 112233
2 firstname doe
2 phone 223344
This is mysql query without condition:
SELECT a.*,
b.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
This is result:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname,phone
[value] => john,112233
)
array(
[id] => 2
[email] => doe#gmail.com
[userid] => 2
[key] => firstname,phone
[value] => doe,223344
)
This is mysql query with condition:
SELECT a.*,
b.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
WHERE b.key = "firstname"
AND b.value LIKE '%jo%'
And this is result:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname
[value] => john
)
But I want this:
array(
[id] => 1
[email] => john#gmail.com
[userid] => 1
[key] => firstname,phone
[value] => john,112233
)
There any way to do this? thank for any help!
Your queries are lacking the GROUP BY clause to get a row per user. Then use a HAVING clause to make sure the aggregated row includes a firstname '%jo%':
SELECT a.*,
GROUP_CONCAT(b.key),
GROUP_CONCAT(b.value)
FROM table1 a
LEFT JOIN table2 b ON a.id = b.userid
GROUP BY a.id
HAVING sum(b.key = 'firstname'
AND b.value LIKE '%jo%') > 0;
true results in 1, false in 0 in MySQL. So checking whether the sum is greater than zero means checking whether the condition is true at least once.
I have a table "projects" and a table "tasks" with hierarchical data in my SQL Database. So the tasks have subtasks which are linked with a "parent"-column to its parentID. The Root-Task-Parent is 0.
There is also a column "project_id" which refers the task to a specific project in the Project-Table. What i want to do now is to copy a whole task with all subtasks and refer it to a new project.
So the SQL-Query would be
INSERT INTO tasks (text, date, parent, projectid)
SELECT text, date, parent, 89
FROM tasks WHERE projectid = 23
where 23 is the id of the old project and 89 is the project to which the data is added.
But the problem is that it keeps the parent value, so my root task is copied properly, but the subtasks still refer to the old tasks. How can i update the parentID as well so the whole tasks and subtasks refer to the new Root Task?
I want to use this in my PHP-Web-Application for a Project-Management-Tool, so that the User can simply choose a "Master-Template" to copy its structure to a new project.
Thank you for your help!
Edit:
#Strawberry: I use dhtmlxgantt to create and update task but i want to solve it with SQL queries. An example Table would look like this:
Screenshot of Database
So in this case i would like to duplicate "Project" to "Project 2" with a new projectID and matching subtasks with parentIDs
I assume that [text] field is unique for each project.
With this assumption, here is my query
--DROP TABLE [Tasks]
-- Create table
CREATE TABLE [dbo].[Tasks](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Text] [varchar](10) NOT NULL, -- Assume that [Text] field is unique for each project
[Name] [varchar](50) NOT NULL,
[ParentId] [bigint] NULL,
[ProjectId] [bigint] NOT NULL,
CONSTRAINT [PK_Tasks] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Tasks] WITH CHECK ADD CONSTRAINT [FK_Tasks_Tasks] FOREIGN KEY([ParentId])
REFERENCES [dbo].[Tasks] ([Id])
GO
-- Remove all the data from the table and reseed the identity value
DELETE FROM [Tasks]
DBCC CHECKIDENT ('Tasks', RESEED, 1)
-- Sample Data population starts here...
INSERT INTO [Tasks] (text, Name, [ParentId], ProjectId)
SELECT 'A', 'A', null, 101 union ALL
SELECT 'B', 'B', null, 101 union ALL
SELECT 'C', 'C', null, 101
INSERT INTO [Tasks] (text, Name, [ParentId], ProjectId)
SELECT 'A1', 'A 1', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A'), 101 union ALL
SELECT 'A2', 'A 2', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A'), 101 union ALL
SELECT 'A3', 'A 3', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A'), 101 union ALL
SELECT 'A4', 'A 4', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A'), 101 union ALL
SELECT 'B1', 'B 1', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'B'), 101 union ALL
SELECT 'B2', 'B 2', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'B'), 101 union ALL
SELECT 'B3', 'B 3', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'B'), 101 union ALL
SELECT 'C1', 'C 1', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'C'), 101 union ALL
SELECT 'C2', 'C 2', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'C'), 101 union ALL
SELECT 'C3', 'C 3', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'C'), 101
INSERT INTO [Tasks] (text, Name, [ParentId], ProjectId)
SELECT 'A11', 'A 11', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A 1'), 101 union ALL
SELECT 'A41', 'A 41', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A 4'), 101
-- Sample Data population ends here...
GO
-- Copy all the data from project 101 and insert it as 102 with parent id as null
INSERT INTO [Tasks] (text, Name, [ParentId], ProjectId) -- other column names can be here...
SELECT text, Name, null, 102 -- Other column values can be here...
FROM [Tasks] where ProjectId = 101
-- Update the parent id using the text field
UPDATE A
SET A.[ParentId] = C.NewParentId
FROM [Tasks] A
INNER JOIN (SELECT Child.text, Parent.[Text] Parenttext
FROM [Tasks] Child
INNER JOIN [Tasks] Parent
ON Child.[ParentId] = Parent.[Id]
WHERE Child.ProjectId = 101
) B
ON A.[Text] = B.[Text]
LEFT JOIN (
SELECT [Id] NewParentId, [Text]
FROM [Tasks]
WHERE ProjectId = 102
) C
ON B.Parenttext = C.text
WHERE ProjectId = 102
SELECT * FROM [Tasks] WHERE ProjectId = 102 Order By [Text]
I hope this may help you
I have 3 mysql tables from where I am trying to fetch data
Table: list
list_id | name | description
-------------------------------------
1234 | name1 | sample description1
1235 | name2 | sample description2
Table: list_to_category
id | list_id | category_id
--------------------------------
1 | 1234 | 1
2 | 1234 | 2
3 | 1234 | 3
4 | 1235 | 2
5 | 1235 | 3
And table: category
id | title | parent_id
--------------------------------
1 | Category 1 | 0
2 | Category 2 | 0
3 | Category 3 | 0
And from PHP SQL query I want to fetch data like below
1. name1 - category 1, category 2, category 3
2. name2 - category 2, category 3
I tried below query
SELECT list.name, category.title FROM list
LEFT JOIN list_to_category
ON list.id = list_to_category.list_id
LEFT JOIN category
ON list_to_category.id = category.id
This gives me only single category name assigned to a list like this
1. name1 - category 1
2. name2 - category 2
Is it possible in single query?
You can use GROUP_CONCAT for this:
select
l.list_id,
l.name,
group_concat(distinct c.title) categories
from list l
left join list_to_category lc
on l.list_id = lc.list_id
left join category c
on lc.category_id = c.id
group by l.list_id
You can try this solution.
select l.list_id, l.name, (select group_concat(c.title) from list_to_category ltc JOIN category c ON c.id=ltc.category_id where ltc.list_id=l.id) from list l
Hope this will help you!!!
Use GROUP_CONCAT for group by "name" to fetch result :
SELECT L.name, GROUP_CONCAT(C.title) as title FROM list L
LEFT outer JOIN list_to_category LC ON L.list_id = LC.list_id
LEFT outer JOIN category C ON LC.category_id = C.id
group by L.name
Use GROUP_CONCAT for group by "list_id" for same name of list to fetch result :
SELECT L.name, GROUP_CONCAT(C.title) as title FROM list L
LEFT outer JOIN list_to_category LC ON L.list_id = LC.list_id
LEFT outer JOIN category C ON LC.category_id = C.id
group by L.list_id
It should be apparent from the code below that I'm no PHP coder. However, this should get the idea across. You can also use javascript/css to handle the transformation, which means things can be even more dynamic...
Oh, and I changed some table/column names - because I like it better that way...
<?php
require('path/to/connection/statements'); // $con
$query = "
SELECT l.list_id
, l.name
, l.description
, c.category_id
, c.title
, c.parent_id
FROM list l
JOIN list_category lc
ON lc.list_id = l.list_id
JOIN category c
ON c.category_id = lc.category_id
ORDER
BY l.list_id
, c.category_id;
";
$result = mysqli_query($con,$query);
$my_array = array();
while($row = mysqli_fetch_assoc($result)){
$my_array[] = $row;
}
$new_array = array();
foreach ($my_array as $row)
{
$new_array[$row['list_id']][$row['name']][$row['description']][] = $row['title'];
}
print_r($new_array);
?>
This will turn an array like this:
Array
(
[0] => Array
(
[list_id] => 1234
[name] => name1
[description] => sample description1
[category_id] => 1
[title] => Category 1
[parent_id] => 0
)
[1] => Array
(
[list_id] => 1234
[name] => name1
[description] => sample description1
[category_id] => 2
[title] => Category 2
[parent_id] => 0
)
[2] => Array
(
[list_id] => 1234
[name] => name1
[description] => sample description1
[category_id] => 3
[title] => Category 3
[parent_id] => 0
)
[3] => Array
(
[list_id] => 1235
[name] => name2
[description] => sample description2
[category_id] => 2
[title] => Category 2
[parent_id] => 0
)
[4] => Array
(
[list_id] => 1235
[name] => name2
[description] => sample description2
[category_id] => 3
[title] => Category 3
[parent_id] => 0
)
)
...into an array like this...
Array
(
[1234] => Array
(
[name1] => Array
(
[sample description1] => Array
(
[0] => Category 1
[1] => Category 2
[2] => Category 3
)
)
)
[1235] => Array
(
[name2] => Array
(
[sample description2] => Array
(
[0] => Category 2
[1] => Category 3
)
)
)
)
try this code
select l.name,c.title
from list_to_category lc join list l on lc.list_id=l.id
join category c on lc.catg_id=c.id