I am pretty sure you guys have a simple and fast solution to my problem but my SQL-Skills are limited and I can't figure it out by my self.
So what I have is something like:
Newsgroup: [Name(PK)]
Article: [Id(PK)] [newsgroupName (FK)] [date:Date] [read:Boolean]
What I want know is a query that gives me the Name of each Newsgroup along with the Count of unread articles, Count of all articles and the date of the most recent one...
Is this even possible to archieve in a single Select-Query?
Thank you guys in advance!
You can simply use the appropriate aggregation functions:
SELECT newsgroupName,
SUM(NOT read) AS countUnread,
COUNT(*) AS countAll,
MAX(date) AS mostRecentDate
FROM Article
GROUP BY newsgroupName;
I guess something like this:
SELECT name, COUNT(countUnread) AS countUnread, COUNT(countRead) AS countRead, MAX(mostRecentDateUnread) AS mostRecentDateUnread, MAX(mostRecentDateRead) AS mostRecentDateRead FROM (
SELECT newsgroupName AS name, COUNT(newsgroupName) AS countUnread, 0 AS countRead, MAX(date) AS mostRecentDateUnread, NULL AS mostRecentDateRead
FROM Article
WHERE read = 0
GROUP BY newsgroupName, read
UNION ALL
SELECT newsgroupName AS name, 0 AS countUnread, COUNT(newsgroupName) AS countRead, NULL AS mostRecentDateUnread, MAX(date) AS mostRecentDateRead
FROM Article
WHERE read = 1
GROUP BY newsgroupName, read
)
GROUP BY name
I haven't tried but in theory with some fix it could work.
Related
I'm using SQLite to deal with tons of data (like 100gb of data).
I need to seach the value of one column in other table in the fastest way possible.
For example, I need to find the following values of Table 1
[COD]
C62
K801
And then find them in Table 2:
[COD_2]
C60-C63
K80-K81
My desired result is something like:
[COD_1] [COD_2]
C62 C60-C63
K801 K80-K81
Since I have a lot of data, it is inefficient to do something like:
SELECT *
FROM TABLE_1, TABLE_2
WHERE COD_1 LIKE '%' || COD_2 || '%';
Instead, I was trying to do this:
SELECT *
FROM TABLE_1
WHERE COD_1 IN (SELECT COD_2 FROM TABLE_2);
Of course that this doesn't result because the codes are not exactly the sames. Is there a way to search for similar values of one column (something like the LIKE operator) in other table by using IN? Or other way that doesn't cross TABLE_1 and TABLE_2?
Thank you!!!
useful to me.
Based on the small data set shown, and my presumed answer to #Shawn's question (K801 is a typo and is meant to be K80 or K81) I assume the following problem description:
Find a row in COD_2 such that the value in COD_1 is between {value1}-{value2} in COD_2; the - being significant and dependable.
I cannot speak to speed, but I would approach it this way:
SELECT value1, value2
from COD_1,COD_2
where value1 between substr(value2,1,instr(value2,'-')-1) and substr(value2,instr(value2,'-')+1)
The thought being: split the value from COD-2 into a "start" and an "end" value.
I use SQLITE3 for my DB,i have 3 table: Doc table (id,name,date),tag table (id,name,count) and the relation table (id_doc, id_tag) that connect doc and tag table (many to many relation). Now i'm stuck on a query: i want to select the id of document related to tag 1,2 and 3 but i can't figure out how to do this.
anyone can help me?
If I understand correctly, you can use aggregation and having. Something like this:
select id_doc
from relation r
where id_tag in (1, 2, 3)
group by id_doc
having count(*) = 3;
In a SQLite3 database, I have a table "projects" which id field is composed the following way:
[user id]_[user's project id]
For example, with user id=45, here is some data:
45_1
45_10
45_102
45_2
45_3
45_4
45_68
45_9
I need to get the max of the project id, which is the number after the '_' delimiter (which is 102 in the example). How can I achieve that?
Thank you in advance.
SELECT max(cast((substr(id, pos + 1) AS integer)) AS project_id
FROM (SELECT *, instr(id,'_') AS pos FROM projects);
select max(cast(replace(id, "45_", "") as integer)) from projects;
Now, I should point out this is not making very good use of SQL. Why not have two fields, so you could have proper foreign keys? It would make your life a lot easier
Second, if you don't only have project id = 45, you will need to use the CONCAT function. But I'm hoping you can figure that part out on your own with the functions above.
Kindly review this simple SQLite-fiddle .
If any word in the column ITEM of table TWO matches any word in the column NAME_2 of table ONE, there should be a result(s).
Tried many permutes, yet not sure how to form the query for achieving this. Should the GLOBclause be used instead of LIKE, or perhaps some other wildcard patterns?
Many thanks in advance!
As per my comment, I think you can make use of instr as well. For example:
SELECT * FROM Table1 T1, Table2 T2 where instr(T2.NAME_2,T1.ITEM);
The above should return rows where T2.NAME contains a string = T1.ITEM
I realise it is possible to create a crosstab within sqlite, but is it possible to dynamically determine the relevant categories/columns at runtime rather than hardcoding them?
Given the following example, it can get rather tedious ...
SELECT
shop_id,
sum(CASE WHEN product = 'Fiesta' THEN units END) as Fiesta,
sum(CASE WHEN product = 'Focus' THEN units END) as Focus,
sum(CASE WHEN product = 'Puma' THEN units END) as Puma,
sum(units) AS total
FROM sales
GROUP BY shop_id
I managed to do this in SQLServer in a stored proceedure before and wondered if there was anything equivalent.
No, you can't do that in SQLite, since analytic means in SQLite lack many usefull features available in heavier RDBMSes. Here is the corresponding ticket, but it is in the pending status.
Old question, but anyway: I faked something like this in Ruby on Rails. For my purposes it works well.
def self.yearstats(attr)
# Determine number of columns
minyear = self.select("strftime('%Y', min(recorded_at)) AS minyear").first.minyear.to_i
maxyear = self.select("strftime('%Y', max(recorded_at)) AS maxyear").first.maxyear.to_i
# Stitch SQL query. Use explicit same column name to not confuse Rails' typecasting.
select_str = ["strftime('#{minyear}/%m/%d %H:%m', recorded_at) AS recorded_at"]
(minyear..maxyear).to_a.each do |y|
# avg because the table might have multiple rows per day
select_str += ["avg(case when strftime('%Y', recorded_at)='#{y}' then #{attr} end) AS value#{y}"]
end
self.select(select_str.join(",")).group("strftime('%m/%d', recorded_at)").all.collect {|row|
[row.recorded_at.utc.to_i*1000] + (minyear..maxyear).to_a.collect { |y| row.send("value#{y}") }
}
end
Note that for the first column I used a (fake) date using a fixed first year so that my graphing routines get a "real" date, not just day/month display. This is a little dirty but it works for my purposes. (Improvements still welcome...)
Instead of getting minyear and maxyear, you might want to do a SELECT DISTINCT.. to get the unique list of categories and modify the code appropriately.