I have a bit of a problem with a query I made, it doesn't fetch all the results there are. It should at least come up with 3 rows but only comes up with one:
SELECT * FROM n_news WHERE article_id IN
(SELECT DISTINCT article_id FROM nk_article_category
WHERE category_id IN (2,10,11,12))
ORDER BY article_featured DESC,article_published DESC
Anybody an idea what I'm doing wrong? MySQL didn't find any errors. Thanks in advance
Left is article_id and right = category_id in table nk_article_category. There is one result way up but didn't see the point to show the whole table
What I see per your posted query data image, your query returning correct result. the rows are all distinct (it will be considered duplicate if both article_id and category_id are same in multiple rows).
BTW, you can change your posted query to a INNER JOIN instead of using sub query like
SELECT t1.*
FROM n_news t1
INNER JOIN nk_article_category t2
ON t1.article_id = t2.article_id
AND t2.category_id IN (2,10,11,12)
ORDER BY t1.article_featured DESC, t1.article_published DESC;
Related
I'm kind of noobie to this, but I'm trying to learn, I have two tables, the first one (NEWS) has all the information about posts of a blog, it has the follow structure:
* NEWS (TABLE 1)
- id_new
- id_category
- date
- ...etc
- **likes**
and I have a second table:
* LIKES (TABLE 2)
- id_like
- id_new
- id_user
- date
- ip_user
So, I want to select all the rows from TABLE 1 to display all the news but also i want to count the likes and get the COUNT of each new as like column.
This approach left joins the NEWS table to a subquery which finds the number of likes for each news story.
SELECT
t1.*,
COALESCE(t2.likes, 0) AS likes
FROM NEWS t1
LEFT JOIN
(
SELECT id_new, COUNT(*) AS likes
FROM LIKES
GROUP BY id_new
) t2
ON t1.id_new = t2.id_new
Note that here a story having no likes would not appear at all in the LIKES table and would receive a count of zero. Also note that I assume that every record in the LIKES table corresponds to a logical like. If not, then the query could be modified to count something else.
You can do it like this
SELECT table1.*, table2.*, count(table2.id_like) as like FROM news AS table1
INNER JOIN likes AS table 2 ON table1.id_new = table2.id_new;
OR
SELECT table1.*, table2.*, count(table2.id_like) as like FROM news AS table1
LEFT JOIN likes AS table 2 ON table1.id_new = table2.id_new;
you can use prepared statement
for example
$stmt = $pdo->prepare("SELECT count(*) FROM TABLE_1);
$stmt2 = $pdo->prepare("SELECT count(*) FROM TABLE_2);
//then execute
just read more on prepared statement
Try this
SELECT n, (SELECT count(*) FROM like l WHERE l.id_new = n.id_new) FROM news n
Use something like :
SELECT *, (SELECT COUNT(*) FROM LIKES WHERE LIKES.id_new =id_new) AS newsLikesCount FROM NEWS ORDER BY date;
This query would return all news and their number of likes
select n1.* , numberOfLikes.number_of_likes
from news n1
left join
(select n.id_news, count(l.id_like) as number_of_likes
from news n
left join likes l on n.id_news = l.id_new
group by n.id_news) numberOfLikes on n1.id_news = numberOfLikes.id_news
The important concepts here is understanding how two tables are joined together (1), how group by works(2), and how to aggregate l.id_likes using count(3).
(1). Left join preserves everything in the NEWS table and join them
with news link to the news.
(2). Then we group the rows base on id_news from the news. However,
mysql gets confused because it doesn't know what to do with id_like
from the likes table that we included in our select clause. Don't
worry my friend, This is where count comes in.
(3). We count the number of id_likes base for each id_news since we
are grouping the rows base on id_news.
I hope this helps. and welcome to StackOverfow. If you find this answer of any other answer helpful please mark it as the solution. That way it will help the community and fellow programmers in the future if they run into the same problem as you. Cheers.
Edit: to include all columns from news table we simply join the result from above back to the news table itself. and we select everything from the news table n1 and only number_of_likes from the result we created above.
I have two tables:
twitterusers table
twittergrowth Table
I am trying to do JOIN these 2 tables, get all fields from twitteruser and selective fields from twittergrowth, then fetch only the last 3 rows from this data.
Expected Output:
Current Output:
I.e the rows are repeating. I want rows unique by ID or usernames, and the last set of timestamps. So it would be the last 3 rows, which has the most recent timestamps.
The code I could type scribble out is :
SELECT
t1.*,
t2.new_followers_count,
t2.new_friends_count,
t2.new_timestamp
FROM twitterusers t1
JOIN twittergrowth t2 on (t1.username=t2.username)
Searched quite few pages/sites, but cant really figure out how to do it. I would appreciate any help. :)
Additionally, I would like to get a LIMIT parameter added to the final result, so that I can paginate the full result.
First you need to find a maximum new_timestamp (latest) within groups of the same user_id and username in twittergrowth table. This is a classic group-wise maximum problem and the subquery tgmax does that. Then you need to join back the same table (tg this time) to get other columns that aren't in the group by clause of subquery and are not used in aggregate functions (like max()). These columns are new_followers_count and new_friends_count.
If you tried to put them in the select of subquery mysql would return values from an unspecified row from the same group and not necessarily the same as the one with the latest timestamp. This is explained here.
Once you get desired output for twittergrowth table the only thing left is to join twitterusers table to get all other columns.
SELECT tu.*, tg.new_followers_count, tg.new_friends_count, tg.new_timestamp
FROM twitterusers tu
JOIN twittergrowth tg
ON tu.user_id = tg.user_id AND tu.username = tg.username
JOIN
( SELECT tgg.user_id, tgg.username, max(tgg.new_timestamp) as latest_timestamp
FROM twittergrowth tgg
GROUP BY tgg.user_id, tgg.username ) tgmax
ON tg.user_id = tgmax.user_id AND tg.username = tgmax.username
AND tg.new_timestamp = tgmax.latest_timestamp
Note that this query would benefit from a composite index on (user_id,username,new_timestamp) in the twittergrowth table.
You need to group by to achieve your expected output.
GROUP BY id
To limit, or split results into pages, you can simply add LIMIT X,Y where X is the starting record and Y is the total number of records.
So a query to pull the expected results you want, but only the first 10 would be like so:
SELECT
t1.*,
t2.new_followers_count,
t2.new_friends_count,
t2.new_timestamp
FROM twitterusers t1
JOIN twittergrowth t2 on t1.username=t2.username
GROUP BY t1.id
LIMIT 0,10
i have two tables in a DB with the following structure:
table 1: 3 rows - category_id, product_id and position
table 2: 3 rows - category_id, product_id and position
i am trying to set table 1 position to table 2 position where category and product id is the same from the tables.
below is the sql i have tried to make this happen but returns MySQL error 1242 - subquery returns more then 1 row
UPDATE table1
SET position = (
SELECT position
FROM table2
WHERE table1.product_id = table2.product_id AND table1.category_id = table2.category_id
)
The solution is very simple and it can be done in two simple steps. The first step is just a preview of what will be changed, to avoid destroying data. It can be skipped if you are confident of your WHERE clause.
Step 1: preview the changes
Join the tables using the fields you want to match, select everything for visual validation of the match.
SELECT t1.*, t2.*
FROM table1 t1
INNER JOIN table2 t2
ON t1.category_id = t2.category_id
AND t1.product_id = t2.product_id
You can also add a WHERE clause if only some of the rows must be modified.
Step2: do the actual update
Replace the SELECT clause and the FROM keyword with UPDATE, add the SET clause where it belongs. Keep the WHERE clause:
UPDATE table1 t1
INNER JOIN table2 t2
ON t1.category_id = t2.category_id
AND t1.product_id = t2.product_id
SET t1.position = t2.position
That's all.
Technical considerations
Indexes on the columns used on the JOIN clause on both tables are a must when the tables have more than several hundred rows. If the query doesn't have WHERE conditions then MySQL will use indexes only for the biggest table. Indexes on the fields used on the WHERE condition will speed up the query. Prepend EXPLAIN to the SELECT query to check the execution plan and decide what indexes do you need.
You can add SORT BY and LIMIT to further reduce the set of changed rows using criteria that cannot be achieved using WHERE (for example, only the most recent/oldest 100 rows etc). Put them on the SELECT query first to validate the outcome then morph the SELECT into an UPDATE as described.
Of course, indexes on the columns used on the SORT BY clause are a must.
You can run this query to see what is happening:
SELECT product_id, category_id, count(*), min(position), max(position)
FROM table2
GROUP BY product_id, category_id
HAVING COUNT(*) > 1;
This will give you the list of product_id, category_id pairs that appear multiple times in table2. Then you can decide what to do. Do you want an arbitrary value of position? Is the value of position always the same? Do you need to fix the table?
It is easy enough to fix the particular problem by using limit 1 or an aggregation function. However, you may really need to fix the data in the table. A fix looks like:
UPDATE table1 t1
SET t1.position = (SELECT t2.position
FROM table2 t2
WHERE t2.product_id = t1.product_id AND t2.category_id = t1.category_id
LIMIT 1
);
I've been racking my brain for hours trying work out how to join these two queries..
My goal is to return multiple venue rows (from venues) based on certain criteria... which is what my current query does....
SELECT venues.id AS ven_id,
venues.venue_name,
venues.sub_category_id,
venues.score,
venues.lat,
venues.lng,
venues.short_description,
sub_categories.id,
sub_categories.sub_cat_name,
sub_categories.category_id,
categories.id,
categories.category_name,
((ACOS( SIN(51.44*PI()/180)*SIN(lat*PI()/180) + COS(51.44*PI()/180)*COS(lat*PI()/180)*COS((-2.60796 - lng)*PI()/180)) * 180/PI())*60 * 1.1515) AS dist
FROM venues,
sub_categories,
categories
WHERE
venues.sub_category_id = sub_categories.id
AND sub_categories.category_id = categories.id
HAVING
dist < 5
ORDER BY score DESC
LIMIT 0, 100
However, I need to include another field in this query (thumbnail), which comes from another table (venue_images). The idea is to extract one image row based on which venue it's related to and it's order. Only one image needs to be extracted however. So LIMIT 1.
I basically need to insert this query:
SELECT
venue_images.thumb_image_filename,
venue_images.image_venue_id,
venue_images.image_order
FROM venue_images
WHERE venue_images.image_venue_id = ven_id //id from above query
ORDER BY venue_images.image_order
LIMIT 1
Into my first query, and label this new field as "thumbnail".
Any help would really be appreciated. Thanks!
First of all, you could write the first query using INNER JOIN:
SELECT
...
FROM
venues INNER JOIN sub_categories ON venues.sub_category_id = sub_categories.id
INNER JOIN categories ON sub_categories.category_id = categories.id
HAVING
...
the result should be identical, but i like this one more.
What I'd like to do next is to JOIN a subquery, something like this:
...
INNER JOIN (SELECT ... FROM venue_images
WHERE venue_images.image_venue_id = ven_id //id from above query
ORDER BY venue_images.image_order
LIMIT 1) first_image
but unfortunately this subquery can't see ven_id because it is evaluated first, before the outer query (I think it's a limitation of MySql), so we can't use that and we have to find another solution. And since you are using LIMIT 1, it's not easy to rewrite the condition you need using just JOINS.
It would be easier if MySql provided a FIRST() aggregate function, but since it doesn't, we have to simulate it, see for example this question: How to fetch the first and last record of a grouped record in a MySQL query with aggregate functions?
So using this trick, you can write a query that extracts first image_id for every image_venue_id:
SELECT
image_venue_id,
SUBSTRING_INDEX(
GROUP_CONCAT(image_id order by venue_images.image_order),',',1) as first_image_id
FROM venue_images
GROUP BY image_venue_id
and this query could be integrated in your query above:
SELECT
...
FROM
venues INNER JOIN sub_categories ON venues.sub_category_id = sub_categories.id
INNER JOIN categories ON sub_categories.category_id = categories.id
INNER JOIN (the query above) first_image on first_image.image_venue_id = venues.id
INNER JOIN venue_images on first_image.first_image_id = venue_images.image_id
HAVING
...
I also added one more JOIN, to join the first image id with the actual image. I couldn't check your query but the idea is to procede like this.
Since the query is now becoming more complicated and difficult to mantain, i think it would be better to create a view that extracts the first image for every venue, and then join just the view in your query. This is just an idea. Let me know if it works or if you need any help!
I'm not too sure about your data but a JOIN with the thumbnails table and a group by on your large query would probably work.
GROUP BY venues.id
I'm fairly new to MYSQL!
I need to make a SQL query where i check how many likes a row has (between two tables)
I found another question that looked like mine, but i can't get it to return anything (even though it doesn't create an error.
query:
SELECT *
FROM likes
INNER JOIN (SELECT likes.like_id,
COUNT(*) AS likes
FROM likes
INNER JOIN uploads ON likes.upload_id=uploads.upload_id
WHERE uploads.upload_date >= DATE_SUB(CURDATE(), INTERVAL 8 DAY)
GROUP BY uploads.upload_id) x ON x.like_id = likes.like_id
ORDER BY x.likes DESC
Link to the original question:
MySQL, Need to select rows that has the most frequent values in another table
Help is much appreciated
Kind regards,
Mathias
Since you didn't post your table structure I'll have to guess..
select someid, count(*) cnt from
(
select * from table1 t1 join table2 t2 on t1.someid = t2.someid
) as q0 group by someid order by cnt desc;
It will need tweaking to fit your schema.