SQL Query wordpress - sql

SQL query
find me all the post tags with the proper count for all the posts under the current category?
example
culture ( culture is the current category name and it has 3 posts associated with it )
culture
post1 post 1 happens to be associated with tag1, tag3
post2 post 2 happens to be associated with tag1
post3 post 3 happens to be associated with tag1, tag4
As a result of the SQL query I'm looking for, I want to get a list as follows
culture
tag1 (3 posts)
tag3 ( 1 post )
tag4 ( 1 post )
and when you click tag1, we get only those (3) posts who have been classified under culture category and that has been tagged as tag1.
I'd like to get this data on the fly when I'm serving the culture page? I know it's an expensive query for run time purposes, but if you leave this aspect aside, how do you do it? will I have to use the wp_query?

Something like this should do the trick:
mysql> select category.category, count(posts.id) from posts join category on
posts.category=category.id group by posts.category;
+----------+-----------------+
| category | count(posts.id) |
+----------+-----------------+
| tag1 | 3 |
| tag2 | 2 |
| tag3 | 1 |
+----------+-----------------+
3 rows in set (0.01 sec)

Related

How can I aggregate values inside a jsonb array using SQL

My data looks something like this:
tags | fullName
----------------------------------------------+------------------------------------------
["tag1", "tag2"] | John
["tag3", "tag1"] | Jane
["tag1", "tag3"] | Bob
tags is a jsonb type and fullName a text in a postgres database
What I'm struggling to do is, create a view such as
tags | count
----------------------------------------------+------------------------------------------
tag1 | 3
tag2 | 1
tag3 | 2
You may use the jsonb_array_elements function to expand the row as array elements before grouping and counting.
See example and working fiddle below.
SELECT
tag_names as tag,
COUNT(1) as count
FROM (
SELECT
jsonb_array_elements(tags) as tag_names
FROM
my_table
) t
GROUP BY tag_names;
tag
count
tag1
3
tag2
1
tag3
2
View on DB Fiddle
Or shorter
SELECT
jsonb_array_elements(tags) as tag,
COUNT(1) as count
FROM
my_table
GROUP BY
tag
View on DB Fiddle

BigQuery: Query to GroupBy Array Column

I have (2) columns in BigQuery table:
1. url
2. tags
URL is a single value, and TAGS is an array(example below):
row | URL &nbsp| TAGS
1 | x.com | donkey
| donkey
| lives
| here
How can I group by TAGS array in BigQuery?
What's the trick to get the following query working?
SELECT TAGS FROM `URL_TAGS_TABLE`
group by unnest(TAGS)
I have tried group by TO_JSON_STRING but it does not give me the desired results
I'd like to see the following output
x.com | donkey | count 2
x.com | lives | count 1
x.com | here | count 1
Below is for BigQuery Standard SQL
#standardSQL
WITH `project.dataset.table` AS (
SELECT 'x.com' url, ['donkey','donkey','lives','here'] tags UNION ALL
SELECT 'y.com' url, ['abc','xyz','xyz','xyz'] tags
)
SELECT url, tag, COUNT(1) AS `count`
FROM `project.dataset.table`, UNNEST(tags) tag
GROUP BY url, tag
with result
Row url tag count
1 x.com donkey 2
2 x.com lives 1
3 x.com here 1
4 y.com abc 1
5 y.com xyz 3

How to find the best match between 2 keywords lists

I'm making an ad network for my specific needs:
User picks keywords and add them to an article
Advertiser picks keywords and add them to his ad
When a viewer goes into the User's article, what I need to find is the ad with the highest amount of matching keywords to that specific article (or any ad if no matching keywords)
User keyword table example:
ArticleID | keyword
1 | funny
1 | memes
1 | lol
2 | boring
Advertiser keyword table example
AdId | keyword
1 | funny
1 | lol
2 | funny
2 | food
3 | kids
So if a viewer will go into the article with id=1, the resulting ad will be
the ad with id=1, because it has matched both "funny" and "lol", a more detailed result:
Result:
AdId | count
1 | 2
2 | 1
3 | 0
How can I build a query to do that?
You could join on the keywords and count the results:
SELECT AdId, COUNT(*)
FROM ad_keywords a
JOIN user_keywords u ON a.keyword = u.keyword
WHERE article_id = 1
GROUP BY AdId
ORDER BY 2 DESC
LIMIT 1

Select all rows that have at least a list of features with wildcard support

given a table definition:
Objects:
obj_id | obj_name
-------|--------------
1 | object1
2 | object2
3 | object3
Tags:
tag_id | tag_name
-------|--------------
1 | code:python
2 | code:cpp
3 | color:green
4 | colorful
5 | image
objects_tags:
obj_id | tag_id
-------|---------
1 | 1
1 | 2
2 | 1
2 | 3
3 | 1
3 | 2
3 | 3
I'd like to select objects that contain all tags from given list with wildcards. Similar question has been asked several times and answer to simpler variant looks more or less like this:
SELECT obj_id,count(*) c FROM objects_tags
INNER JOIN objects USING(obj_id)
INNER JOIN tags USING(tag_id)
WHERE (name GLOB 'code*' OR name GLOB 'color*')
GROUP BY obj_id
HAVING (c==2)
However this solution doesn't work with wildcards. Is it possible to create similar query that would return objects that for each given wildcard query returned at least 1 tag? Checking if c>=2 doesn't work because one wildcard tag can return multiple results while another may return 0 still passing query even though it shouldn't.
I considered builting dynamic query built by client software that would consist of N INTERSECTs (one per tag) because there's probably not going to be many of them but it sounds like really dirty solution and if there's any more SQL way then I'd prefer to use it.
SQLite supports WITH clause so I would try to use it to determine all tags first, and then use these tags to find objects in the below way.
The example (demo) is made for PostGreSQL because I could not run SQLIte on any online tester, but I belive you will convert it easily to SQLite:
this query retrieves all tags:
WITH tagss AS (
SELECT * FROM Tags
WHERE tag_name LIKE 'code:%' OR tag_name LIKE 'color:%'
)
SELECT * FROM tagss;
| tag_id | tag_name |
|--------|-------------|
| 1 | code:python |
| 2 | code:cpp |
| 3 | color:green |
and the final query uses the above subquery in this way:
WITH tagss AS (
SELECT * FROM Tags
WHERE tag_name LIKE 'code:%' OR tag_name LIKE 'color:%'
)
SELECT obj_id,count(*) c
FROM objects_tags
INNER JOIN tagss USING(tag_id)
WHERE tag_name IN ( SELECT tag_name FROM tagss)
GROUP BY obj_id
HAVING count(*) >= (
SELECT count(*) FROM tagss
)
| obj_id | c |
|--------|---|
| 3 | 3 |

Get all column entries for each unique id in a table

I have a table structured something like this:
profile | tag
-------------------------
p1 | tag1
p1 | tag2
p1 | tag3
p2 | tag1
p2 | tag3
I want to run a query that returns something like:
tag1, tag2, tag3
tag1, tag3
Basically, for each unique profile, a list of the tags that exist in the table.
Is that possible, or do I need to have a unique column in my result for each tag I care about?
Thanks!
This returns what you want:
SELECT array_agg(tag)
FROM table1
GROUP BY profile
Or :
SELECT string_agg(tag, ',')
FROM table1
GROUP BY profile
string_agg let's you specify what delimiter you want and ORDER the results in each row.
SQLFIDDLE DEMO