Count string occurrences within a list column SQL/Grafana - sql

I have a table in the following format:
| id | tags |
|----|-------------------------|
|1 |['Car', 'Plane', 'Truck']|
|2 |['Plane', 'Truck'] |
|3 |['Car', 'Plane'] |
|4 |['Plane'] |
|5 |['Boat', 'Truck'] |
How can I create a table that gives me the total number of occurrences of each item in all cells of the "tags" column? Items ideally do not include single quotes, but may if necessary.
The resulting table would look like:
| tag | count |
|-------|-------|
| Car | 2 |
| Plane | 4 |
| Truck | 3 |
| Boat | 1 |
The following does not work because it only counts identical "tags" entries rather than comparing list contents.
SELECT u.id, count(u.tags) as cnt
FROM table u
group by 1
order by cnt desc;
I am aware of this near-identical question, but they are using Snowflake/SQL whereas I am using MySQL/Grafana so the accepted answer uses functions unavailable to me.

Related

Returning rows that contain text from another table

I have two tables Main and Lookup
Main has a column called [Promotion Codes List] that is a string of different promo codes comma separated.
Lookup has a column of all the individual promotion codes called [Promotion Codes].
I am trying to create a view of the Main table that will filter Main table if if Main.[Promotion Codes List] contains a code that is in the Lookup.[Promotion Codes] table.
Main Table sample data
|id|Promotion Codes List|
|--| ------------------ |
|1 | BR-Coll-210731-10903, BR-NFRD-210731-10124 |
|2 | BR-Coll-210731-10903, BR-Deal-210731-11265 |
|3 | BR-Coll-210731-11037, BR-Deal-210731-11275 |
|4 | BR-Coll-210731-11037 |
Lookup Table sample data
|id|Promotion Codes|
|--| ------------- |
|1 | BR-NFRI-251231-04855 |
|2 | BR-Deal-210731-11265 |
|3 | BR-Coll-210731-11402 |
|4 | BR-Deal-210731-11275 |
|5 | BR-Coll-210731-11037 |
Desired output
Main Table
|id|Promotion Codes List|
|--| ------------------ |
|2 | BR-Coll-210731-10903, BR-Deal-210731-11265 |
|3 | BR-Coll-210731-11037, BR-Deal-210731-11275 |
|4 | BR-Coll-210731-11037 |
I started off playing around with
SELECT Promotion Codes List, CASE WHEN EXISTS (SELECT *
FROM dbo.[Lookup] B
WHERE B.[Promotion Codes] = A.Promotion Codes List) THEN 'common' ELSE 'not common' END AS valid FROM dbo.Main AS A
and it works if there is are exact matches in row, but as you can see in the main table there can be multiple br codes in one record so I tried to add a like statement somewhere but couldn't figure it out.
Thanks !
Try below
SELECT Promotion Codes List, CASE WHEN EXISTS (SELECT 1
FROM dbo.[Lookup] B
WHERE A.[Promotion Codes List] like '%'+B.[Promotion Codes]+'%') THEN 'common' ELSE 'not common' END AS valid FROM dbo.Main AS A

Trying to use SQL to group accounts by number of sub-types

I'm using a table that houses account info. These accounts can have between 1 and 6 unique sub types. Currently it only tracks between single and multi subtypes but doesn't show the totals of how many of each multi sub-type account there are (how many accounts with 2 subtypes vs. 3 subtypes and so on). I'm looking for a wholly SQL way to view how many of each grouping of account types. There are a LOT of accounts in the table so pulling it manually isn't really an option. Is there a way I can get a count of each of the amount of sub-type groupings?
| account | Sub-Type | Single_V_Multi |
|---------|--------- | -------------- |
|123456789|123456789 | Multi |
|123456789|123456790 | Multi |
|123456789|123456791 | Multi |
|123456792|123456792 | Single |
|123456793|123456793 | Multi |
|123456793|123456794 | Multi |
|123456795|123456795 | Single |
|123456796|123456796 | Single |
|123456797|123456797 | Single |
|123456798|123456798 | Single |
|123456799|123456799 | Multi |
|123456799|123456800 | Multi |
|123456799|123456801 | Multi |
|123456799|123456802 | Multi |
From this example I'd be looking to get separate counts of the Account column based on the number of unique Sub-Type. What I've done so far is a query that groups the Sub-Types:
SELECT account, COUNT(DISTINCT(Sub-Type)) as BAN_SUB_COUNT
FROM Table
Which give the output:
| account | BAN_SUB_COUNT |
| ------- | ------------- |
|123456789| 3 |
|123456792| 1 |
|123456793| 2 |
|123456795| 1 |
|123456796| 1 |
|123456797| 1 |
|123456798| 1 |
|123456799| 4 |
What I need from this is a way to get a separate count of accounts for each of the distinct BAN_SUB_COUNT entries. Ideally it would be along the lines of:
| BAN_SUB_COUNT |count of Accounts|
| ------------- | --------------- |
| 1 | 5 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
Sorry for any confusion and I hope I'm explaining myself better here!
You just need to wrap your query with another one:
select ban_sub_count, count(distinct account) as count_of_accounts
from (
SELECT account, COUNT(DISTINCT Sub-Type ) as BAN_SUB_COUNT
FROM Table
group by account
)z
group by ban_sub_count
Output:
BAN_SUB_COUNT
count of Accounts
1
5
2
1
3
1
4
1
I try to answer your question:
select a2.*,a.`count_sub_type`
FROM (
select count(`sub-type`) as count_sub_type,`sub-type` from account group by `sub-type`
) a
left join account a2 on a2.`sub-type` = a.`sub-type`;
output :
|account |sub-type|single_v_multi|count_sub_type|
|--------|--------|--------------|--------------|
|account6|type1 |multiview |3 |
|account5|type1 |single |3 |
|account1|type1 |single |3 |
|account4|type2 |single |2 |
|account2|type2 |single |2 |
|account6|type3 |single |2 |
|account3|type3 |single |2 |
Best regards,

SELECTing Related Rows Based on a Single Row Match

I have the following table running on Postgres SQL 9.5:
+---+------------+-------------+
|ID | trans_id | message |
+---+------------+-------------+
| 1 | 1234567 | abc123-ef |
| 2 | 1234567 | def234-gh |
| 3 | 1234567 | ghi567-ij |
| 4 | 8902345 | ced123-ef |
| 5 | 8902345 | def234-bz |
| 6 | 8902345 | ghi567-ij |
| 7 | 6789012 | abc123-ab |
| 8 | 6789012 | def234-cd |
| 9 | 6789012 | ghi567-ef |
|10 | 4567890 | abc123-ab |
|11 | 4567890 | gex890-aj |
|12 | 4567890 | ghi567-ef |
+---+------------+-------------+
I am looking for the rows for each trans_id based on a LIKE query, like this:
SELECT * FROM table
WHERE message LIKE '%def-234%'
This, of course, returns just three rows, the three that match my pattern in the message column. What I am looking for, instead, is all the rows matching that trans_id in groups of messages that match. That is, if a single row matches the pattern, get all the rows with the trans_id of that matching row.
That is, the results would be:
+---+------------+-------------+
|ID | trans_id | message |
+---+------------+-------------+
| 1 | 1234567 | abc123-ef |
| 2 | 1234567 | def234-gh |
| 3 | 1234567 | ghi567-ij |
| 4 | 8902345 | ced123-ef |
| 5 | 8902345 | def234-bz |
| 6 | 8902345 | ghi567-ij |
| 7 | 6789012 | abc123-ab |
| 8 | 6789012 | def234-cd |
| 9 | 6789012 | ghi567-ef |
+---+------------+-------------+
Notice rows 10, 11, and 12 were not SELECTed because there was not one of them that matched the %def-234% pattern.
I have tried (and failed) to write a sub-query to get the all the related rows when a single message matches a pattern:
SELECT sub.*
FROM (
SELECT DISTINCT trans_id FROM table WHERE message LIKE '%def-234%'
) sub
WHERE table.trans_id = sub.trans_id
I could easily do this with two queries, but the first query to get a list of matching trans_ids to include in a WHERE trans_id IN (<huge list of trans_ids>) clause would be very large, and would not be a very inefficient way of doing this, and I believe there exists a way to do it with a single query.
Thank you!
This will do the job I think :
WITH sub AS (
SELECT trans_id
FROM table
WHERE message LIKE '%def-234%'
)
SELECT *
FROM table JOIN sub USING (trans_id);
Hope this help.
Try this:
SELECT ID, trans_id, message
FROM (
SELECT ID, trans_id, message,
COUNT(*) FILTER (WHERE message LIKE '%def234%')
OVER (PARTITION BY trans_id) AS pattern_cnt
FROM mytable) AS t
WHERE pattern_cnt >= 1
Using a FILTER clause in the windowed version of COUNT function we can get the number of records matching the predefined pattern within each trans_id slice. The outer query uses this count to filter out irrelevant slices.
Demo here
You can do this.
WITH trans
AS
(SELECT DISTINCT trans_id
FROM t1
WHERE message LIKE '%def234%')
SELECT t1.*
FROM t1,
trans
WHERE t1.trans_id = trans.trans_id;
I think this will perform better. If you have enough data, you can do an explain on both Sub query and CTE and compare the output.

Column 'Course.Course_Name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

I need to link two tables columns, please help me. This my code:
SELECT Student.Stu_Course_ID, Course.Course_Name, COUNT(Student.Stu_ID) AS NoOfStudent FROM Student
INNER JOIN Course
ON Student.Stu_Course_ID=Course.Course_ID
GROUP BY Stu_Course_ID;
This is my course table:
__________________________________________
|Course_ID | Course_Name |
|1 | B.Eng in Software Engineering |
|2 | M.Eng in Software Engineering |
|3 | BSC in Business IT |
I got number of students from student table
_____________________________
|Stu_Course_ID | NoOfStudents |
|1 | 30 |
|2 | 12 |
|3 | 20 |
This is what i want
____________________________________________________________
|Stu_Course_ID | Course_Name | NoOfStudents|
|1 | B.Eng in Software Engineering | 30 |
|2 | M.Eng in Software Engineering | 12 |
|3 | BSC in Business IT | 20 |
You need to add Course.Course_Name to your group by clause:
SELECT Student.Stu_Course_ID,
Course.Course_Name,
COUNT(Student.Stu_ID) AS NoOfStudent
FROM Student
INNER JOIN Course
ON Student.Stu_Course_ID=Course.Course_ID
GROUP BY Student.Stu_Course_ID, Course.Course_Name;
Imagine the following simple table (T):
ID | Column1 | Column2 |
----|---------+----------|
1 | A | X |
2 | A | Y |
Your query is similary to this:
SELECT ID, Column1, COUNT(*) AS Count
FROM T
GROUP BY Column1;
So, you know you have 2 records for A in column1, so you expect a count of 2, however, you are also selecting ID, there are two different values for ID where Column1 = A, so the following result:
ID | Column1 | Count |
----|---------+----------|
1 | A | 2 |
Is no more or less correct than
ID | Column1 | Count |
----|---------+----------|
2 | A | 2 |
This is why ID cannot be contained in the select list, unless it included in the group by clause, or as part of an aggregate function.
For what it's worth, if Course_ID is the primary key in the table Course then following query is legal according to the SQL Standard, and will work in Postgresql, and I suspect at some point Microsoft will build this functionality into SQL Server too:
SELECT Course.Course_ID,
Course.Course_Name,
COUNT(Student.Stu_ID) AS NoOfStudent
FROM Student
INNER JOIN Course
ON Student.Stu_Course_ID=Course.Course_ID
GROUP BY Course.Course_ID;
The reason for this is that since Course.Course_ID is the primary key of Course there can be no duplicates of this in the table, therefore there can only be one value for Course_name for each Course_ID
give columns names after group by statements which you want to retreive so you have to also give Course.Course_Name as well...

select multi row inside of a table (not same condition)

I try to explain an issue I have faced nowadays.
Actually I have designed a table in order to track the changes applying by users inside of a depot of NLP engine.
I have two table named Token And Lexeme. each token has an id that directly connect to a row of lexeme table. and always I can find the latest and updated lexemes by looking up to token table.
here is their scheme:
Token Table:
+-----+----------+----------+
| Id | token |LexemeId* |
+-----+----------+----------+
LexemeId refers to a row inside of lexeme table.
Lexeme Table:
+-----+---------------------+-------------+
| Id | some information |UpdatedFrom* |
+-----+---------------------+-------------+
* UpdatedFrom field refers another row inside of Lexeme Table.
Null means there is no more rows related to this token(lexeme).
an example:
Token Table:
+-----+----------+----------+
| 0 | A |4 |
| 1 | B |1 |
+-----+----------+----------+
Lexeme Table:
+-----+----------------------+-------------+
| 0 | A information#1 |NULL |
| 1 | B information |NULL |
| 2 | A information#2 |0 |
| 3 | A information#3 |2 |
| 4 | A information#4 |3 |
+-----+----------------------+-------------+
I hope I could clear the air.
I want to write a store procedure to collect all records related to each token. for example for token 'A', I'm expected to have an array (or data table) looks like this:
+-----+----------------------+-------------+
| id | informations | updated from|
+-----+----------------------+-------------+
| 0 | A information#1 |NULL |
| 2 | A information#2 |0 |
| 3 | A information#3 |2 |
| 4 | A information#4 |3 |
+-----+----------------------+-------------+
anybody has any idea to help me....
my knowledge on sql transcript is summarized to Update, Insert and select statements, not more!
thanks in advanced...
Assuming this is in an RDBMS that supports recursive CTEs, try:
with cte as
(select t.id TokenId, t.token, l.Id, l.SomeInformation, l.UpdatedFrom
from Token t
join Lexeme l on t.LexemeId = l.id
union all
select t.TokenId, t.token, l.Id, l.SomeInformation, l.UpdatedFrom
from cte t
join Lexeme l on t.UpdatedFrom = l.id)
select Id, SomeInformation, UpdatedFrom
from cte
where TokenId=0 /* token = 'A' */
SQLFiddle here.