MYSQL: two results in one row - php

Iam solving an issue. Iam having 2 tables:
ORDERS - which defines customer order
+-------------------+-------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| customer_id | int(11) | NO | MUL | NULL | |
| from_date | date | YES | | NULL | |
| datum_dodani | date | NO | | NULL | |
| popis | text | NO | | NULL | |
| status | tinyint(4) | NO | | 1 | |
| cena | varchar(8) | NO | | NULL | |
| vytvoril | tinyint(4) | NO | MUL | NULL | |
| vytvoreno | timestamp | NO | | CURRENT_TIMESTAMP | |
| vyresil | tinyint(4) | YES | | NULL | |
| prirazena_skupina | tinyint(4) | YES | | NULL | |
| narocnost | smallint(6) | YES | | NULL | |
| cas | varchar(6) | YES | | NULL | |
| priorita | tinyint(1) | NO | | 0 | |
+-------------------+-------------+------+-----+-------------------+----------------+
and POLOZKY_OBJEDNAVKY which defines each row of customer order:
+-----------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| order_id | int(11) | YES | MUL | NULL | |
| servis_id | tinyint(4) | YES | MUL | NULL | |
| cena | int(11) | YES | | NULL | |
| pocet | tinyint(4) | YES | | NULL | |
| popis | text | YES | | NULL | |
| bike | text | YES | | NULL | |
+-----------+------------+------+-----+---------+----------------+
These two tables are linked via polozky_objednavky.order_id -> orders.id
And the problem is that Iam not able to create query which would return something like this:
+-------------------+-------------+--------------+------------------------+
| orders.id | customer_id | orders.status| polozky_objednavky.bike|
+-------------------+-------------+--------------+------------------------+
| 1 | 23 | 2| 24, 25, 46|
| 2 | 25 | 5| 36|
So that means that in column polozky_objednavky.bike there will be select which returns 3 rows from POLOZKY_OBJEDNAVKY with key POLOZKY_OBJEDNAVKY.ORDER_ID = ORDERS.ID
Hope i explained it well and sorry for dumb question, but I tried to select it with JOINS or select from select but has not succeed :(
Thank you,
M.

You need to join the tables. Try this:
SELECT o.id AS orders_id,
o.customer_id,
o.status,
p.bike
FROM ORDERS AS o
LEFT OUTER JOIN POLOZKY_OBJEDNAVKY AS p
ON p.order_id = o.id
If you have a specific condition just add it to the end as a WHERE clause.
You can read about joins at w3school and sitepoint

I think you need an aggregation query with group_concat():
SELECT o.id AS orders_id, o.customer_id, o.status,
GROUP_CONCAT(p.bike SEPARATOR ', ') as bikes
FROM ORDERS o JOIN
POLOZKY_OBJEDNAVKY po
ON p.order_id = o.id
GROUP BY o.id, po.customer_id;

Related

get users that did not buy a product

I have three tables
users table
+--------------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------------+--------------+------+-----+---------+----------------+
| Id | bigint | NO | PRI | NULL | auto_increment |
| AccountNumber | varchar(50) | YES | | NULL | |
| DisplayName | varchar(255) | YES | MUL | NULL | |
| ParentAccountId | bigint | YES | MUL | NULL | |
| AccountTypeRef | bigint | YES | MUL | NULL | |
| PhoneNo | varchar(255) | YES | | NULL | |
| FaxNo | varchar(50) | YES | | NULL | |
| Website | varchar(200) | YES | | NULL | |
| Email | varchar(100) | YES | | NULL | |
| StateRef | bigint | YES | MUL | NULL | |
| Address | longtext | YES | | NULL | |
| PostalCode | varchar(50) | YES | | NULL |
products table
+-------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+----------------+
| Id | bigint | NO | PRI | NULL | auto_increment |
| ProductId | bigint | YES | MUL | NULL | |
| PackName | varchar(255) | YES | | NULL | | |
| Price | double | YES | | NULL | |
| OnlineInfoAddress | varchar(255) | YES | | NULL | |
| Description | longtext | YES | | NULL | |
| IsDelete | tinyint | YES | | NULL | |
| CreateUserId | bigint | YES | | NULL | |
| CreateDate | datetime | YES | | NULL | |
| EditDate | datetime | YES | | NULL | |
| EditUserId | bigint | YES | | NULL | |
| Tag | int | YES | | NULL | |
| Ref | varchar(50) | YES | | NULL | |
| deleted_at | timestamp | YES | | NULL | |
+-------------------+--------------+------+-----+---------+----------------+
users_buy table
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| Id | bigint | NO | PRI | NULL | auto_increment |
| users_id | bigint | YES | MUL | NULL | |
| product_id | bigint | YES | MUL | NULL | |
| BuyDate | datetime | YES | | NULL | |
| CountBuy | int | YES | | NULL | |
| TotalPrice | double | YES | | NULL | |
| Description | longtext | YES | | NULL | |
| invoiceNumber | varchar(255) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
I want to get users who did not buy a specific product
for example, user number 20 bought 5 product with ids [1,2,3,4,5]
and user number 19 bought 3 product with ids [1,2,3]
And user number 18 bought 2 product with ids [1,3]
I want to get users who did not buy any product with the id 5
ie I want user 18 and 19
How can I do this?
This will list of all users that did not buy product id 5:
SELECT *
FROM users
WHERE
Id NOT IN (
SELECT users_id
FROM users_buy
WHERE product_id = 5
)
One more solution used LEFT JOIN:
SELECT users.*
FROM users
LEFT JOIN users_buy
ON users_buy.users_id = users.id AND users_buy.product_id = 5
WHERE users_buy.user_id IS NULL;
The above query will return records from users table have not matched rows in users_buy table with product_id 5

Join two queries from different tables

How can I join those two queries into one?
The first query getting all posts_id from specific category; postId from post_category table equals to id in post table
select distinct postId
from post_category
where categoryId='125' or categoryId='3'
then I want to join them so it will select all postId from post_category in post table
SELECT * FROM post <<query one join>> AND approve=1"
post
+--------------+-----------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------------------+------+-----+---------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| autor | varchar(40) | NO | MUL | | |
| date | datetime | NO | MUL | 0000-00-00 00:00:00 | |
| short_story | text | NO | MUL | NULL | |
| full_story | text | NO | MUL | NULL | |
| xfields | text | NO | | NULL | |
| title | varchar(255) | NO | MUL | | |
| descr | varchar(200) | NO | MUL | | |
| keywords | text | NO | | NULL | |
| category | varchar(200) | NO | MUL | 0 | |
| alt_name | varchar(200) | NO | MUL | | |
| comm_num | mediumint(8) unsigned | NO | MUL | 0 | |
| allow_comm | tinyint(1) | NO | | 1 | |
| allow_main | tinyint(1) unsigned | NO | MUL | 1 | |
| approve | tinyint(1) | NO | MUL | 0 | |
| fixed | tinyint(1) | NO | | 0 | |
| allow_br | tinyint(1) | NO | | 1 | |
| symbol | varchar(3) | NO | MUL | | |
| tags | varchar(255) | NO | MUL | | |
| metatitle | varchar(255) | NO | | | |
| FileTempUUID | varchar(11) | YES | | NULL | |
+--------------+-----------------------+------+-----+---------------------+----------------+
post_category;
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| cid | bigint(11) | NO | PRI | NULL | auto_increment |
| postId | int(11) | NO | | NULL | |
| categoryId | smallint(6) | NO | | NULL | |
+------------+-------------+------+-----+---------+----------------+
As your tables schema, Try this join:
SELECT
p.*
FROM
post p
LEFT OUTER JOIN post_category c ON (c.postId = p.id)
WHERE
c.categoryId IN (125,3) AND p.approve=1
GROUP BY p.id
Also using GROUP BY p.id to distinct posts, if needed.
Something like this should do it:
SELECT DISTINCT postId post.* FROM post_category
LEFT JOIN post ON post_category.postId = post.id
WHERE (categoryId='125' OR categoryId='3') AND post.approve = 1
I think the Variable {$join} refers to the string This is totally Wrong, There is special Keyword called Join in SQL, I will try Hardly to write SQL Statement to do what I guessed that u want
$sql = "Select a.postId, a.categoryId, b.* from post_category a, post b where a.postId = b.id and (a.categoryId='125' or a.categoryId='3')
#Edit
If i understood ur comment your code would result in this
SELECT * FROM post select distinct postId
from post_category
where categoryId='125' or categoryId='3' AND approve=1"
Which is totally wrong SQL Statement

Query with 3 tables and a MAX

I have these following tables:
Table "Questoes";
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| id_quest | int(11) | NO | | NULL | |
| questao | varchar(255) | NO | | NULL | |
| nivel | int(11) | NO | | NULL | |
| tipo | varchar(255) | NO | | NULL | |
+----------+--------------+------+-----+---------+----------------+
Table "Resultados";
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| id_user | int(11) | NO | MUL | NULL | |
| nivel | int(11) | NO | | NULL | |
| pontuacao | int(24) | NO | | NULL | |
| data | date | NO | | NULL | |
+-----------+---------+------+-----+---------+----------------+
And table "utilizador";
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| id_user | int(11) | NO | PRI | NULL | auto_increment |
| id_tipo | int(11) | NO | | 1 | |
| username | varchar(50) | NO | UNI | NULL | |
| password | varchar(20) | NO | | NULL | |
| nome | varchar(50) | NO | | NULL | |
| email | varchar(100) | NO | | NULL | |
| data_nasc | text | NO | | NULL | |
| e_valido | smallint(6) | NO | | 0 | |
+-----------+--------------+------+-----+---------+----------------+
What i need is the maximum of score (field "pontuacao") of each level (field "nivel") in the table "resultados" to the best player.
To get the players name, will be through the field "id_user" in table "resultados".
I have this, but doesn'st work:
SELECT u.id_user, MAX(u.pontuacao), u.nivel, u.data, l.nivel, r.id_user, r.username
FROM questoes l, resultados u, utilizador r
WHERE u.nivel = l.nivel AND r.id_tipo=1 AND u.id_user=r.id_user
GROUP BY u.nivel
SELECT a.id_user, r.username, b.pontuacao, b.nivel
FROM resultados a
INNER JOIN utilizador r on a.id_user=r.id_user
INNER JOIN (SELECT u.nivel, MAX(u.pontuacao) pontuacao
FROM resultados u
GROUP BY u.nivel) b ON a.nivel = b.nivel AND a.pontuacao = b.pontuacao
It doesn't work because you are relying on an extension to MySQL that doesn't do what you expect. When using group by, just be sure all the columns in the select are either aggregated or in the group by.
What you want is more like:
SELECT u.id_user, r2.pontuacao, u.nivel, u.data, l.nivel, r.id_user, r.username
FROM questoes l join
resultados u
u.nivel = l.nivel join
utilizador r
on u.id_user = r.id_user join
(select r2.nivel, max(r2.pontuacao) as maxp
from resultados r2
group by r2.nivel
) r2
on u.nivel = r2.nivel and u.pontuacao = r2.maxp
WHER r.id_tipo = 1
GROUP BY u.nivel;
This calculates the maximum value as a subquery and then joins it back in. You may not need the group by after this. Also, I fixed the joins so they use proper ANSI syntax.

MySQL Query - Select all posts and count comments for each one

It's 3:30 AM in my country so I need to sleep but I can't without this:
I'm trying to get all posts (using Zend_Db) and count comments for each one.
Schema
blog_posts:
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| content | text | NO | | NULL | |
| alias | varchar(100) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
| created_date | datetime | NO | | NULL | |
| modified_date | datetime | YES | | NULL | |
| thumbnail | varchar(255) | YES | | NULL | |
+---------------+------------------+------+-----+---------+----------------+
And here's blog_comments:
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | NULL | |
| post_id | int(11) | NO | | NULL | |
| comment | text | NO | | NULL | |
| created_date | datetime | NO | | NULL | |
| modified_date | datetime | YES | | NULL | |
+---------------+------------------+------+-----+---------+----------------+
Note: the blog_comments.post_id is linked with blog_posts.id.
I would like a resulting table like that:
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| content | text | NO | | NULL | |
| alias | varchar(100) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
| created_date | datetime | NO | | NULL | |
| modified_date | datetime | YES | | NULL | |
| thumbnail | varchar(255) | YES | | NULL | |
+---------------+------------------+------+-----+---------+----------------+
| TEMPOROARY COLUMN IN OBJECT ($post->comment) |
+---------------+------------------+------+-----+---------+----------------+
| comments | | | | | |
+---------------+------------------+------+-----+---------+----------------+
Now, here's the query I have for now:
SELECT `p`.*, `c`.*
FROM `blog_posts` `p`
LEFT JOIN (
SELECT COUNT(*)
FROM `blog_comments` `c`
WHERE c.post_id = p.id
) ON `p`.`comments`;
But it give me an error:
Error Code: 1248. Every derived table must have its own alias
So if someone can help me, it would be very appreciated!
IMPORTANT NOTE
I'm using Zend_Db and Zend_Db_Select so I must be able to use the functions like joinLeft() or anything I need.
This is in my model for the select():
$select = $this->table->select();
if ($alias) {
$select->where('alias = ?', $alias);
return $this->table->fetchRow($select);
}
if ($withComments) {
// I WILL PLACE THE CODE HERE, EXEMPLE:
$select->joinLeft(...);
}
SELECT p.*, x.*
FROM blog_posts p
LEFT JOIN
(
SELECT post_id, COUNT(*) as cc
FROM blog_comments
GROUP BY post_id
) x
ON x.post_id = p.id;

Number of games a particular user has played today where there is no data

I'm trying to get the number of games that summoners in the queue have played today. I have tried several queries. The closest I have gotten is:
SELECT
s.summoner,
s.wins,
COUNT(*) as playedToday
FROM summoners s
LEFT JOIN teams_players tp ON tp.summoner_id = s.summoner
LEFT JOIN teams t ON t.id = tp.team_id
LEFT JOIN matches b ON t.id = b.blue_id
WHERE
b.played_on = DATE(NOW())
s.in_queue;
But that doesn't give the count per-user. It just gets the overall count.
None of the tables have any data on any of the summoners. What I'd like is something like:
+-----------------+------+-------------+
| summoner | wins | gamesPlayed |
+-----------------+------+-------------+
| DotAliscious | 353 | 0 |
| Kraator | 440 | 0 |
| Nammon | 667 | 0 |
| VictorousSecret | 843 | 0 |
| Canas | 544 | 0 |
| Sprognak | 502 | 0 |
| Ghostilocks | 808 | 0 |
| b0b d0e | 224 | 0 |
| Metroshica | 339 | 0 |
| RubenatorX | 478 | 0 |
+-----------------+------+-------------+
I can't think how to express this problem generically, which is why I haven't found a solution.
My data set. Note that teams.id matches up with matches.blue_id and matches.purple_id.
mysql> DESCRIBE summoners;
+--------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| icon | int(11) | NO | | 0 | |
| summoner | varchar(32) | NO | UNI | NULL | |
| skype | varchar(32) | NO | | NULL | |
| email | varchar(32) | NO | | NULL | |
| in_queue | tinyint(1) | NO | | 0 | |
| wins | int(11) | NO | | 0 | |
| level | int(11) | NO | | 1 | |
| lan_wins | int(11) | NO | | 0 | |
| played_today | int(11) | NO | | 0 | |
+--------------+-------------+------+-----+---------+----------------+
10 rows in set (0.00 sec)
mysql> DESCRIBE matches;
+-----------+-------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| blue_id | int(11) | NO | MUL | NULL | |
| purple_id | int(11) | NO | MUL | NULL | |
| status | varchar(32) | NO | | display | |
| played_on | datetime | NO | | 2012-04-06 13:53:55 | |
+-----------+-------------+------+-----+---------------------+----------------+
5 rows in set (0.00 sec)
mysql> DESCRIBE teams;
+---------+-------------+------+-----+------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| outcome | varchar(32) | NO | | incomplete | |
+---------+-------------+------+-----+------------+----------------+
2 rows in set (0.00 sec)
mysql> DESCRIBE teams_players;
+-------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| team_id | int(11) | NO | MUL | NULL | |
| summoner_id | int(11) | NO | MUL | NULL | |
+-------------+---------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
You're going to want to use a subselect to get the count of records that meet the condition, and that will return you a 0 if the condition is false. Something along the lines of
(SELECT COUNT(*) FROM matches b WHERE b.blue_id = t.id AND b.played_on = DATE(NOW())) AS playedToday
and you will want to remove the LEFT JOIN to the matches table and the WHERE clause checking the date.
Your played_on is datetime and you are comparing it with date maybe that's your problem. YOu should try:
WHERE
DATE(b.played_on) = DATE(NOW())
Also what do you mean by s.in_queue? Did you forget the AND? Do you mean
WHERE
DATE(b.played_on) = DATE(NOW())
AND
s.in_queue;

Categories