How can I LEFT JOIN a table and COUNT the rows? - mysql

I want to list my projects and the amount of posts each project has:
`projects` `posts`
------------------ ------------------
| `id` | `name` | | `id` | `name` |
------------------ ------------------
| 1 | Cat | | 1 | Cat |
| 2 | Dog | | 2 | Cat |
| 3 | Bird | | 3 | Dog |
| 4 | Frog | ------------------
------------------
$projects = $db->query('SELECT *,
COUNT(posts.*) AS posts
FROM projects
LEFT JOIN posts ON projects.name=posts.name
')->fetchAll(PDO::FETCH_ASSOC);
foreach($projects as $row) {
echo "Project ".$id." has ".$posts ".posts.".<br>";
}
So as a result I expect:
Project 1 has 2 posts.
Project 2 has 1 posts.
Project 3 has 0 posts.
Project 4 has 0 posts.
But I get an error message:
Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or
access violation: 1064 You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near '*) AS posts,
So I changed posts.* into posts.id
But then my result is:
Project 1 has 3 posts.
I am actually now confused how to achieve the result I need.

The error was raised because of count(po.*) you must count for one column only inside of a count() function.
So, we want to find out how many times will find the 'name' column in posts table for a corresponding id column in projects table so we should count posts.name from posts joined with projects.
We need left join because we want also find out if it does not have corespondent (count(po.name) =0))
The query below will do the job:
SELECT p.*,COUNT(po.name) AS posts
FROM projects p
left join posts po on p.name = po.name
group by p.id
You can check here: http://sqlfiddle.com/#!9/3e9d4b/4

Related

How to get the last 3 rows from MYSQL database

I wanted to get only the last 3 rows of my database here is the query that I tried
select top 3 * from poem where MemberID = 54;
But there was an error
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '3 * from poem where MemberID = 54' at line 1
This is an example of one of the data stored in my table poem
MariaDB [bigproject]> select PoemID, Title, Description from poem where MemberID = 79;
+--------+------------------------+--------------------+
| PoemID | Title | Description |
+--------+------------------------+--------------------+
| 34 | Everything Has Changed | EHC |
| 52 | Kapono | Poetic |
| 53 | Love under the sky | How is your heart? |
| 54 | Imaginary | Imagine me |
+--------+------------------------+--------------------+
4 rows in set (0.000 sec)
I only wanted to get the last 3 rows of this.
Thank you!!

Select all values from a table plus a column returning 1/0 whether a record exists in other table [duplicate]

This question already has answers here:
Selecting boolean in MySQL based on contents of another table
(2 answers)
Closed 4 years ago.
I need some help with a MySQL query which is bringing me a headache.
Basically I have two tables which are related. The first table is called 'books' and it contains the basic information about a book. Then I have an other table called 'user_books' which is related to the previous table and other table (which is irrelevant in the question). This is how the books table looks like:
| b_id | b_name | b_description |
---------------------------------------------------
| 1 | Book1 | Description1 |
| 2 | Book2 | Description2 |
The 'user_books' table has this content:
| ub_userid | ub_bookid | ub_rating | ub_default |
------------------------------------------------------
| 10 | 1 | 5 | 1 |
The user_books table has two primary keys: ub_userid and ub_bookid.
Now I need to make a query which returns all books of the books table and for each book the rating of a given user and a column that in case that there is a record for the book in the user_books table return 1 but if there isn't any book with that bookid return 0.
My desired output given the user 10 would be this:
| b_id | b_name | b_description | ub_default | active |
----------------------------------------------------------
| 1 | Book1 | Description1 | 1 | 1 |
| 2 | Book2 | Description2 | 0 | 0 |
----------------------------------------------------------
I'm using MySQL 5.7
Thanks so much in advance for any kind of help.
select
b.b_id,
b.b_name,
b.b_description,
coalesce(ub.ub_default, 0) as ub_default,
case
when ub.ub_userid is null then 0
else 1
end as active
from books b left outer join
user_books ub
on ub.ub_bookid = b.b_id
where
ub.ub_userid = 10;
This doesn't do any aggregation, so if you have multiple user_books records for one books record, then the books record will be duplicated. But, it shows how to join against a missing row (outer join) and test for whether that outer join row is present or missing.
Here's a SQL Fiddle for MySQL 5.6 http://sqlfiddle.com/#!9/b70ff8/4/0

MySQL Cannot Show Column Name "Group"

I have a table which:
| fullname | onepreference | group | batch |
+------------+---------------+-------+-------+
| First Name | 1 | 1 | 2015 |
| First Name | 2 | 1 | 2015 |
| First Name | 1 | 2 | 2007 |
| First Name | 4 | 2 | 2014 |
+------------+---------------+-------+-------+
I am trying to write the following query:
SELECT
fullname,
onepreference,
group
FROM mytable
WHERE batch = 2015;
But it shows the following error
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'group from mytable where batch=2015' at line 1
I think group column is a keyword of mysql. But I want to get the data of group column. Is there any possibilities available to take the group value?
group is a reserved word in mysql. so you have to escape it whith backticks:
select fullname, onepreference, `group` from add_application_form where batch=2015;
group is a reserved word and you need to use backticks:
SELECT
fullname,
onepreference,
`group`
FROM add_application_form
WHERE batch=2015;
Check the list here and avoid those keyword as table and column names.

mutual non-mutual friend query mysql

Hello everyone I have been trying this for ages now.
I have read many questions here and tried adapting the varied solutions to my needs but without results.
History:
for an event there are many participants.
the participants all meet one another at the event and give out "likes" to all the other participants they actually like.
At the end of the event the admin inserts all the likes for each participant of THAT event, and the system will find the mutual likes (friendship)
Problem:
While inserting the likes i would like (pun) the system to detect weather a friendship is already established (from other events also) and if so avoid to display that user name when setting the likes.
Here are the tables that I'm using (mysql)
wp_fd_users
id | user_name | user_gender | .. etc
wp_fd_matches
id | event_id | event_user_id | event_user_match_id | ... etc
Example of the match table
1 | 1 | 1 | 3 | ...
2 | 1 | 1 | 4 | ...
3 | 1 | 2 | 6 | ...
4 | 1 | 3 | 1 | ...
where you can clearly see that 1 <-> 3 have a mutual relationship and 1 likes 4 but not mutually.
I would need a query that returns all results that AVOID relationships that have been established in one single event.
An occurance like this:
1 | 1 | 1 | 3 | ...
2 | 1 | 1 | 4 | ...
3 | 1 | 2 | 6 | ...
4 | 2 | 3 | 1 | ...
would not trigger the like because it happens in two separate events
Hope it's clear
YOur question is a little unclear. I am going by: "I would need a query that returns all results that AVOID relationships that have been established in one single event."
The following self join accomplishes this:
select m1.*
from wp_fd_matches m1 left outer join
wp_fd_matches m2
on m1.event_id = m2.event_id and
m1.event_user_id = m2.event_user_match_id
m1.event_user_match_id = m2.event_user_id
where m2.id is null
It looks for the matching record. However, by using a left outer join, it is getting all records. It then filters out the ones with a match.

SQL concatenate rows query

Say we have a table
table posts
+---------+-----------+--------------------------------+
| postId | title | status | bodyText |
+---------+-----------+--------------------------------+
| 1 | Hello! | deleted | A deleted post! |
| 2 | Hello 2! | deleted | Another one! |
| 3 | New 1 | new | A new one! |
| 4 | New 2 | new | A new one again! |
Can we, in SQL, retrieve a concatenation of a field across rows, by issuing a single query, not having to do the join up in a loop in our back-end code?
Something like
select title from posts group by status ;
Should give a result like
+---------+--------------------+
| deleted | Hello!, Hello 2! |
| new | New 1, New 2 |
If you use MySQL then you can use GROUP_CONCAT:
SELECT status, GROUP_CONCAT(title)
FROM posts
GROUP BY status
In MySQL:
SELECT status, GROUP_CONCAT(title SEPARATOR ', ')
FROM posts
GROUP BY
status
In PostgreSQL:
SELECT status,
ARRAY_TO_STRING(
ARRAY(
SELECT title
FROM posts pi
WHERE pi.status = po.status
))
FROM posts po
GROUP BY
status
You didn't indicate a particular SQL engine.
In Firebird (from 2.1) you can use the LIST() function. Take a look at: link text
It's an aggregate function to do exactly what you need.
I guess it exists in other engines (LIST in Sybase SQL Anywhere, GROUP_CONCAT in MySQL)