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;
Related
I have two tables, users and lifts.
On my UI (php webpage), I have two drop downs (as well as others, irrelevant), one drop down is [userlastname, userfirstname], and the other is [destination]
the query i am using is this:
SELECT * FROM lifts l JOIN users u ON l.user_id=u.uid GROUP BY l.id;
which gives me the list of usernames in users (correctly)
[Harvey Fletcher]
[Ronald McDonald]
[Harvey Fletcher]
and also a list of all destinations
[Destination 1]
[Destination 2]
[Destination 3]
But as you can see from the usernames list, [Harvey Fletcher] has appeared twice. How can I stop this from happening? Table structure below.
Users:
+---------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+----------------+
| uid | int(10) | NO | PRI | NULL | auto_increment |
| title | varchar(10) | NO | | NULL | |
| firstname | varchar(100) | NO | | NULL | |
| lastname | varchar(100) | NO | | NULL | |
| email | varchar(500) | NO | | NULL | |
| password | varchar(500) | NO | | NULL | |
| reg_no | varchar(10) | YES | | NULL | |
| vehicle_make | varchar(50) | YES | | NULL | |
| vehicle_colour | varchar(25) | YES | | NULL | |
| licence_no | varchar(50) | YES | | NULL | |
| address_line1 | varchar(75) | NO | | NULL | |
| address_line2 | varchar(75) | NO | | NULL | |
| town_city | varchar(75) | NO | | NULL | |
| postcode | varchar(10) | NO | | NULL | |
| reputation_positive | int(10) | YES | | 0 | |
| reputation_negative | int(10) | YES | | 0 | |
| telephone_number | char(11) | NO | | NULL | |
+---------------------+--------------+------+-----+---------+----------------+
Lifts:
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
| user_id | int(10) | NO | | NULL | |
| lift_to | varchar(50) | NO | | NULL | |
| lift_from | varchar(50) | NO | | NULL | |
| quote_price | varchar(50) | NO | | NULL | |
| available_seats | int(2) | YES | | 1 | |
| depart_date | varchar(20) | NO | | NULL | |
| depart_time | varchar(10) | NO | | NULL | |
| pickup_location | varchar(100) | NO | | NULL | |
+-----------------+--------------+------+-----+---------+----------------+
Info:
Harvey Fletcher is only in users table once
Harvey Fletcher has two 'lifts', which is why it appears twice.
Ronald McDonald only has one, so only appears once, but if I added a second lift, would be displayed 2 times.
Group your query to users instead of lifts:
SELECT * FROM lifts l JOIN users u ON l.user_id=u.uid GROUP BY u.uid;
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;
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
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.
I have the following MySQL query and tables from which I am querying:
SELECT
`Song`.`id`,
`Song`.`file_name`,
`User`.`first_name`,
`Vote`.`value`,
Sum(`Vote`.`value`) AS score
FROM `songs` AS `Song`
LEFT JOIN votes AS `Vote` ON (`Song`.`id`=`Vote`.`song_id`)
LEFT JOIN `users` AS `User` ON (`Song`.`user_id` = `User`.`id`)
GROUP BY `Vote`.`song_id`
LIMIT 20;
mysql> describe songs;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| file_name | varchar(255) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
| created | datetime | NO | | NULL | |
| modified | datetime | NO | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql> describe users;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(255) | NO | | NULL | |
| password | varchar(255) | NO | | NULL | |
| first_name | varchar(255) | NO | | NULL | |
| last_name | varchar(255) | NO | | NULL | |
| is_admin | tinyint(1) | NO | | 0 | |
| created | datetime | NO | | NULL | |
| modified | datetime | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
mysql> describe votes;
+----------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| value | int(11) | NO | | NULL | |
| song_id | int(11) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
| created | datetime | NO | | NULL | |
| modified | datetime | NO | | NULL | |
+----------+----------+------+-----+---------+----------------+
This query functions just like I want except for one thing. The value returned in the field Vote.value is not from a row that is associated with the user who is logged into the application. I need the score value to be a sum of all the values no matter which user it is associated with, but the Vote.value field should belong to the logged in user (each user only gets one vote record per song).
My first thought is to somehow sort the table so that when the group by happens the vote record for the logged in user is at the top but I have no idea how to do a sort that forces an arbitrary value to the top. Any ideas would be very helpful.
and a third join
LEFT JOIN votes AS `VotePerUser` ON (`Song`.`id`=`Vote`.`song_id`
AND `Song`.`user_id`=`votes`.`user_id`)
and replace the Vote.value with VotePerUser.Value