How to get only 1 row of each similar content? - php

I Have a private message system on my site and i'm trying to pull all subject's on the messages.
I need to show any subject once.
so if I have this subjects:
hey
hello
hey
good morning
good morning
I need to print this:
hey
hello
good morning
I can just cross it out with if, but I guess there is a better way with sql.
Thank you.

Option 1 : DISTINCT
SELECT DISTINCT subject
FROM my_table
Option 2 : GROUP BY
SELECT subjects
FROM my_table
GROUP BY subjects
Difference between GROUP BY and DISTINCT
Distinct is used to filter unique records out of the records that satisfy the query criteria.
Group by clause is used to group the data upon which the aggregate functions are fired and the output is returned based on the columns in the group by clause. It has its own limitations such as all the columns that are in the select query apart from the aggregate functions have to be the part of the Group by clause.
See this and this for the reference .

Try something like:
SELECT DISTINCT subject FROM emails;

If you use SQL.
select distinct subjects
from YOUR_TABLE.
or
Select subjects
from YOU_TABLE
group by subjects

Related

SQL Select the column if the value is like with multiple columns

I need to create a autocomplete search with ajax. The suggestions should only contain the 10 most entered results. The search query has to check multiple columns if the value is like my variable.
But my problem is to create the query and the php logic for that.
Is there any plugin or something simular for that?
How can I select a column if the value in it is like my variable?
I need to create a count query, which counts (in all columns) "how often is here the full word (splitted by spaces)" <- which is like the found one (to get the relevance)
At the end I need to sort the found entries by their relevance to provide the 10 most relevant entries.
(The real query checks for more columns than just 2, but for dummy reasons are 2 okay)
The query which selects the rows where the value is like...
select * from
(
(select department from entries where department like '%myVariable%')
OR
(select grade from entries where grade like '%myVariable%')
)
I think you know what I mean. Does anyone have any hints, suggestions, examples or useful links for me?
Thanks in advance!
Best regards,
FriaN
Why not use union all here?
select department from entries where department like '%myVariable%'
union all
select grade from entries where grade like '%myVariable%'
Then this should order the results for you:
select department, count(*) cnt from (
select department from entries where department like '%myVariable%'
union all
select grade from entries where grade like '%myVariable%')a
group by department
order by count(*) desc

Postgres query SELECT when field is set

I have a table topics. And I have two queries which select different data, one for the table votings and one from the table messages. topics has a field m_group which is a foreign key for messages. This field can either be NULL or a group for entries in messages (group is a field in this table). If this field is set to a group, it should perform query 1 to select all messages or if it is not set it should perform query 2 to select all votings for this specific topic. I'm using Postgres and PHP on an Apache Webserver.
Now my question is what is the recommended way to go. I came up with two solutions (not sure if solution 2 is actually possible, haven't tried it yet).
Solution 1
First select the field m_group. Then determine if it is set via PHP and perform the associated query.
Solution 2
Use a IF THEN ELSE statement
Basically the query should then look something like this
IF t.m_group IS NULL
THEN
query2
ELSE
query1
As already mentioned, I'm not sure if solution 2 is possible. What would be the best way to handle this? Solution 1 performs two queries, I think this is inefficient.
UPDATE
As mentioned above, it should perform the queries for a specific topic. You have the id of this topic. How can you specify this in solution 2? And does the IF THEN ELSE statement already know the alias t for topics, if that is specified in the queries?
If I understand you right, you need to use two subqueries as sets of data, while you should use one of them as a source depending on what's in the m_group field. Your second approach is good if you only select a few rows. However, if you need to grab a lot of data from the table, this way you will need to perform too many subqueries. I would rather first grab all the data you need from topics and then select what you need with both queries.
Pseudo SQL query will look like that:
with t1 as (select t.id, group_m, ... from topics t where t.m_group is not null),
t2 as (select t.id, ... from topics t where t.m_group is null)
select id, title, SUM(subtable_id) AS votes
from query1
join t1 on t1.id = query1.id and...
union
select id, title, SUM(subtable_id) AS votes
from query2
join t2 on t2.id = query2.id and...

How to make MySQL DISTINCT work with multiple columns using table join?

How can I made the query below select only one record? Each game has two records (one record for each team). If there are nine (9) games there would be eighteen (18) records. I want to select only one record, not both records, for each game.
If I use DISTINCT with only one column (game_id_2) it works fine or returns only nine records. However, if I try to add more columns the DISTINCT directive no longer works.
SELECT DISTINCT
B.game_id_2,
B.GmeYear,
B.GmeMonth,
B.GmeDay,
B.GmeDate,
B.GmeTime,
B.GmeOrd,
B.Home,
B.DivPlay,
L.Instit,
FROM BsbGme B LEFT JOIN LeagueTeam L
ON B.team_id = L.team_id
WHERE B.NonD1=''
AND B.team_id IN ($participant_str)
AND B.GmeMonth = $GameMonth
AND B.GmeDay = $GameDay
ORDER BY B.game_id_2 ASC
According to w3schools dot come the DISTINCT directive is supposed to work with multiple columns. But it's not working with multiple columns in my example.
w3schools example:
SQL SELECT DISTINCT Syntax
SELECT DISTINCT column_name,column_name
FROM table_name;
http://www.w3schools.com/sql/sql_distinct.asp
I have looked at several of the other answers to this same question on StackOverflow but I can't get any of them to work.
Thank you in advance.
try using brackets DISTINCT (your, columns) or use GROUP BY.

Include NULL as 0 in COUNT SQL Query

I know for a fact this has been asked a few times before, but none of the answered questions relating to this seem to work or are far too confusing for me..
I should probably explain.
I'm trying to create an AJAX script to run to order some results by the number of 'Likes' it has.
My current code is this:
SELECT COUNT(*) AS total, likes.palette_id, palette.*
FROM likes LEFT JOIN palette ON likes.palette_id = palette.palette_id
GROUP BY likes.palette_id
ORDER BY total DESC
Which works fine, however it doesn't list the results with 0 likes for obvious reasons, they don't exist in the table.
I've attached images of the current tables:
Likes table:
http://imgur.com/EGeR3On
Palette table:
http://imgur.com/fKZmSve
There are no results in the likes table until the user clicks 'Like'. It is then that the database gets updated and the palette_id and user_id are inserted.
I'm trying to count how many times *palette_id* occurs in the likes table but also display 0 for all palettes that don't appear in the likes table.
Is this possible? If so, can someone help me out at all?
Thank you
It might not be the exact MySQL syntax (I'm used to SQL Server), but should be pretty straight forward to translate if needed.
SELECT p.*, IFNULL(l.total, 0) AS total
FROM palette p
LEFT JOIN (
SELECT palette_id, COUNT(*) AS total
FROM likes
GROUP BY palette_id
) l
ON l.palette_id = p.palette_id
ORDER BY total
Try this:
SELECT COUNT(likes.palette_id) AS total, palette.palette_id, palette.*
FROM palette LEFT JOIN likes ON likes.palette_id = palette.palette_id
GROUP BY palette.palette_id
ORDER BY total DESC
EDIT:
In regards to the discussion about listing columns that are not in the GROUP BY, there's a good explanation in this MySql documentation page.
MySQL extends the use of GROUP BY so that the select list can refer
to nonaggregated columns not named in the GROUP BY clause. This means
that the preceding query is legal in MySQL. You can use this feature
to get better performance by avoiding unnecessary column sorting and
grouping. However, this is useful primarily when all values in each
nonaggregated column not named in the GROUP BY are the same for each
group. The server is free to choose any value from each group, so
unless they are the same, the values chosen are indeterminate.
In this example, the palette information not added to the GROUP BY will be the same for each group because we are grouping by palette_id so there won't be any issue using palette.*
Your join is written backwards. It should be palette LEFT JOIN likes, because you want all rows in palette and rows in likes, if they exist. The "all rows in palette" will get you a palette_id for the entries there without any matching "likes."

mysql join not working

I have two tables: "users" and "posts." The posts table has a 'post' column and a 'poster_id' column. I'm working on a PHP page that shows the latest posts by everyone, like this:
SELECT * FROM posts WHERE id < '$whatever' LIMIT 10
This way, I can print each result like this:
id: 43, poster_id:'4', post: hello, world
id: 44, poster_id:'4', post: hello, ward
id: 45, poster_id:'5', post: oh hi!
etc...
Instead of the id, I would like to display the NAME of the poster (there's a column for it in the 'users' table)
I've tried the following:
SELECT *
FROM posts
WHERE id < '$whatever'
INNER JOIN users
ON posts.poster_id = users.id LIMIT 10
Is this the correct type of join for this task? Before learning about joins, I would query the users table for each post result. The result should end up looking similar to this:
id: 43, poster_id:'4', name:'foo', post: hello, world
id: 44, poster_id:'4', name:'foo', post: hello, ward
id: 45, poster_id:'5', name:'fee', post: oh hi!
etc...
Thanks for helping in advance.
WHERE clause must come after the FROM clause.
SELECT posts.*, users.* // select your desired columns
FROM posts
INNER JOIN users ON posts.poster_id = users.id
WHERE id < '$whatever'
LIMIT 10
the SQL Order of Operation is as follows:
FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause
UPDATE 1
For those column names that exists on both tables, add an ALIAS on them so it can be uniquely identified. example,
SELECT post.colName as PostCol,
users.colName as UserCol, ....
FROM ....
on the example above, both tables has column name colName. In order to get them both, you need to add alias on them so in your front end, use PostCol and UserCol to get their values.
Try:
SELECT *
FROM posts
INNER JOIN users ON posts.poster_id = users.id
WHERE posts.id < '$whatever'
LIMIT 10
Got the syntax a little incorrect.
Should be
SELECT * FROM posts
INNER JOIN users ON posts.poster_id = users.id
WHERE id < '$whatever' LIMIT 10
The answers already given tell you the main reason for your query not working at all (ie the WHERE clause should come after the JOIN clauses), however, I'd like to make a couple of additional points:
I would suggest using an OUTER JOIN for this. It probably won't make much difference, but in the event of a post record having an invalid poster_id, an INNER JOIN will mean the record is dropped from the results, whereas an OUTER JOIN will mean that the record is included, but the values from the users table will be null. I imagine you don't want to ever have an invalid poster_id on the posts table, but broken data does happen even in the best regulated system, and it is helpful in these cases to still get the data from the query.
I would strongly suggest not doing SELECT *, and instead itemising the fields you want to get back from the query. SELECT * has a number of problems, but it's particularly bad when you have multiple tables in the query, because if you have fields with the same name on both tables, (eg id), then it becomes very hard to distinguish which one you're working with, as your PHP recordset won't include the table reference. Itemising the fields may make your query string longer, but it won't make it any slower - if anything it'll be quicker - and it will be easier to work with in the long run.
Neither of these points are essential; the query will work without them (as long as you switch the WHERE clause to after the JOIN), but they may improve your query and hopefully also improve your understanding of SQL.

Categories