DISTINCT and RND() on joined tables - php

I’m really struggling with how to write a query which randomly selects 50 DISTINCT random titles from one table in my MySQL database and then selects 1 random excerpt from each title from a separate table. The first table is titles and the second is excerpts.
I’ve tried two queries nested together but this either doesn’t work or returns duplicate titles despite supposedly being DISTINCT.
Could somebody please, PLEASE help me with where I’m going wrong?!
My existing PHP:
$distincttitlequery = “SELECT DISTINCT titleid FROM titles ORDER BY rand() LIMIT 50”;
$distincttitleresult = mysql_query($cxn,$distincttitlequery);
while ($distinctqueryreturn = mysqli_fetch_assoc($distincttitlequery))
{
extract ($distinctqueryreturn);
$selectedtitle = $titleid;
$randomexcerptquery = “SELECT excerpts.titleid, excerpts.excerptid, excerpts.excerptsynopsis, title.titleid, title.title FROM excerpts INNER JOIN titles ON excerpts.titleid=title.titleid WHERE titleid = ‘$selectedtitle’ ORDER BY rand() LIMIT 1”;
$randomexcerptresults = mysql_query($cxn,$randomexcerptquery);
while ($randomexcerptreturn = mysqli_fetch_assoc($randomexcerptquery))
{
[ECHO RESULTS HERE]
}};
I’ve read in similar posts about GROUP BY but I need to create a query which deals with distinct, random and joined tables and I have absolutely no idea where to start!
My existing code uses DISTINCT on multiple columns and joins the tables but this leads to titles being repeated in returned results. I can LIVE with that but I’d love to perfect it!
Thank you in advance for your help with this.

In mysql 8 you can use row_number to get 1 random row per titleid
SELECT
titleid,title,excerptid,excerptsynopsis
FROM (
SELECT
e.titleid, e.excerptid, e.excerptsynopsis
,ROW_NUMBER() OVER( PARTITION BY e.titleid ORDER BY rand()) rn
, t.title
FROM excerpts e
INNER JOIN (SELECT DISTINCT titleid FROM titles ORDER BY rand() LIMIT 50) t ON e.titleid=t.titleid
) t1
WHERE rn = 1

Related

Select over multiple tables. Wordpress

I'm trying to figure out how to do this on my own but it looks like a dead end to me.
I am working under wordpress framework and with some custom tables.
The result i am trying to achieve is very simple but the way to get there is just too much for my head right now.
I need to select the top 50 results from tableOne based on the ammount of times that the id from tableOne is mentioned in tableTwo under some simple where conditions.
Using $wpdb class for the latest WordPress build, what can i use to achieve this?
Thanks
This is the Simple tableOne Query to get all posts:
$allPosts = $wpdb->get_results("SELECT * FROM pokeGrid_images WHERE status='0' ORDER BY tempo DESC LIMIT ".$limit." OFFSET ".$offset."");
Now i need the first 50 results from this table, based on the number of times their id is mentioned on the second table with this structure: http://prntscr.com/byz2qw
Edit:
http://prntscr.com/byz79b
Note: Basically this is a forum, table one has the posts, table 2 the upvotes.
The expression must gather the most upvoted posts for the last X days.
If it was 1 post the expression would be Select Count(*) FROM tableTwo Where tempo > then ".$variableWithUnixTimeDIff."
column tempo is a now() timestamp.
Thanks
Note: Basically this is a forum, table one has the posts, table 2 the
upvotes. The expression must gather the most upvoted posts for the
last X days. If it was 1 post the expression would be Select Count(*)
FROM tableTwo Where tempo > then ".$variableWithUnixTimeDIff."
SELECT *, Sum(score) AS totalScore FROM tableTwo INNER JOIN tableOne ON tableTwo.memeID = tableOne.id GROUP BY memeID ORDER BY totalScore DESC;
Try this query.
//Edit - I just created a sample table with my own data. I only created the tableTwo, where this query did work:
SELECT *, Sum(score) AS totalScore FROM tableTwo GROUP BY memeID ORDER BY totalScore DESC
So after that, just inner join data from tableOne and it will work!

Get most popular tags from mysql normalized tables

I'm building my own tag system for a forum I'm making. Everything is working perfectly, but I am trying to echo a list of the most popular tags but I can't find which query to use..
My tables look like this:
I need a list of the 20 most popular tags, so the tag_names of which the tag_id appear the most in the article_tag_xref table. Anyone who has an idea what the query should look like? Thanks!
You can use the following query:
SELECT t.tag_id, t.tag_name, COUNT(article_id) AS cnt
FROM Article_Tag_Xref AS a
INNER JOIN Tag AS t ON a.tag_id = t.tag_id
GROUP BY t.tag_id, t.tag_name
ORDER BY COUNT(article_id) DESC LIMIT 20
COUNT(article_id) returns the number of appearances of each tag_ig in the Article_Tag_Xref table. Thus, order by this count in descending order and applying a LIMIT 20 returns the 20 most popular tag_ig values.
The following should work out for you, as you only asked about the tag_names without their count.
SELECT tag_name
FROM Tag
WHERE tag_id IN ( SELECT tag_id, COUNT(article_id)
FROM Article_Tag_Xref
GROUP BY tag_id
ORDER BY COUNT(article_id) DESC
LIMIT 20)
The subquery returns the top 20 tag_ids and their count.

Query doesn't fetch all results

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;

Get the list of ten top publishers in database

I've got following tables in my MySQL database:
USERS
iduser nick password
ARTICLES
idarticles iduser text
How can I get by one SQL query the list of e.g. 10 top publishers of articles ordering by the count of added articles? Is there any way to do that? I'm using PHP to ask database.
Yes, this should be quite easy via JOIN and COUNT(). Something like the following
SELECT `users`.`iduser`, COUNT(`articles`.`idarticles`) AS `total_articles`
FROM `users`
INNER JOIN `articles` ON `users`.`iduser` = `articles`.`iduser`
GROUP BY `users`.`iduser`
ORDER BY `total_articles` DESC
LIMIT 10
A little explaining:
COUNT() will get you what it says - a count of all relevant entries in articles
INNER JOIN will pair all entries that belong together (defined via ON)
GROUP BY tells SQL that you are interested in various results, each differing by iduser (without this, you'd get all articles counted in the first returned row)
ORDER BY .. DESC is important to get the result in a descending order (so most published first)
LIMIT 10 does exactly that

MySql - Joining another table with multiple rows, inserting a query into a another query?

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

Categories