T-SQL Select and count from different table? - asp.net

I have a table (Threads) containing a field (id). I would like to select every row from Threads, as well as the number of rows in the table Posts where the field Posts.thread is the same as Threads.id.
How can this be done in SQL?
(Something like this pseudo-SQL: SELECT *, COUNT(* FROM Posts WHERE Posts.id=Threads.id) FROM Threads)

Sure - something like this?
SELECT
t.ThreadID,
(SELECT COUNT(*) FROM dbo.Posts p WHERE p.ThreadID = t.ThreadID)
FROM
dbo.Threads t

SELECT t.id, COUNT(p.thread)
FROM Threads AS t
LEFT OUTER JOIN Posts AS p
ON t.id = p.thread
GROUP BY t.id

Related

maraidb CTE, how to reuse selected order?

I haev a query where I have a CTE that selects some rows in a specfic order, and I want to use that same order for my main data set Im returning:
WITH selector (id) AS (SELECT id FROM ..... ORDER BY something)
SELECT ...
FROM users u
JOIN selector s ON s.id = u.id
ORDER BY FIELD(u.id, (SELECT id FROM selector))
but this isn't valid syntax in the last ORDER BY FIELD statement as the sub query returns more than one row, is it possible to achieve something like this?
The function FIELD() needs a list of values and not the results of a query.
You can use the function GROUP_CONCAT() to create a comma separated list of ids returned by the CTE, ordered by your conditions and then the function FIND_IN_SET() to join the CTE to the table and sort by its result:
WITH selector (ids) AS (SELECT GROUP_CONCAT(id ORDER BY something) FROM .....)
SELECT ...
FROM users u INNER JOIN selector s
ON FIND_IN_SET(u.id, s.ids)
ORDER BY FIND_IN_SET(u.id, s.ids)
Or, use ROW_NUMBER() window function:
WITH selector (id, rn) AS (SELECT id, ROW_NUMBER() OVER (ORDER BY something) FROM .....)
SELECT ...
FROM users u INNER JOIN selector s
ON s.id = u.id
ORDER BY s.rn

Two queries in one statment

I want in put two queries in one statement how can i do that in this state?
1
stmt = `SELECT Comments.*, Users.username,Users.avatar from Users
INNER JOIN Comments ON Comments.users_id =Users.users_id
WHERE Comments.post_id= 1`
2
`SELECT COUNT(*) comment FROM Comments WHERE Comments.post_id= 1`;
Cross join the 1st query to the 2nd:
SELECT c.*, u.username, u.avatar, t.counter
FROM Users u INNER JOIN Comments c
ON c.users_id = u.users_id
CROSS JOIN (SELECT COUNT(*) counter FROM Comments WHERE post_id = 1) t
WHERE c.post_id = 1
I don't know much about SQLite, but in SQL Server you can use ";" to use multiple queries.
Maybe it does work for SQLite.
You can use GROUP BY on comments table in a way:
'SELECT COUNT(Comments.<id>), Comments.*, Users.username,Users.avatar
from Users INNER JOIN Comments ON Comments.users_id =Users.users_id
WHERE Comments.post_id = 1 GROUP BY Comments.<id>';
*This syntax of GROUP BY clause follows PostgreSQL. You might need to tweak according to the syntax followed by sqlite.

Subquery with alias in SQLite

I have a query that I run in PostgreSQL like this:
select
c_count, count(*) as custdist
from (
select
c_custkey,
count(o_orderkey)
from
customer left outer join orders on
c_custkey = o_custkey
and o_comment not like '%special%requests%'
group by
c_custkey
)as c_orders (c_custkey, c_count)
group by
c_count
order by
custdist desc,
c_count desc;
And I wanted to run it on SQLite, but I got this error: Error: near" (": syntax error. Maybe he doesn't recognize this as c_orders (c_custkey, c_count).
Is there any way to rewrite this query to execute in SQLite?
SQLite does not allow redefining/renaming columns for an nested, aliased query. You can do that with a WITH clause (i.e. Common Table Expression; CTE). Or you can add aliases to the nested query columns directly using AS keyword.
Interesting that this is exactly how the outer query columns are named. Just use the same pattern for the nested query. I don't use PostgreSQL, but why not add aliases directly on each column and complicate it by using different syntax for each part of the query?
select
c_count, count(*) as custdist
from (
select
c_custkey,
count(o_orderkey) AS c_count
from
customer left outer join orders on
c_custkey = o_custkey
and o_comment not like '%special%requests%'
group by
c_custkey
) AS c_orders
group by
c_count
order by
custdist desc,
c_count desc;

SQLite left join with two conditions in right table

I have two tables: a list of items and the sort order scoped on some group_id.
Items belong either to a group or are common (group_id=0).
I want to query all common and group items with the correct sort order for this group. All items with sort order -1 must be dismissed. Items with no associated sort_order must be included.
Wrong (Naive) Query:
SELECT items.*
FROM items LEFT JOIN sort_order ON items._id = sort_order.item_id
WHERE (items.group_id=0 OR items.group_id=14)
AND sort_order.entity_id=14
AND sort_order.sort >= 0
Behaves like a inner join - items with no corresponding sort_order are dismissed.
Slow Query:
SELECT items.*
FROM items LEFT JOIN sort_order
ON items._id = sort_order.item_id AND sort_order.entity_id=14
WHERE (items.group_id=0 OR items.group_id=14)
AND sort_order.sort >= 0
With ~5.000 entries in sort_order and ~1500 items the query takes ~2 seconds.
My question: Is there a better/correct way to handle this?
Maybe nonsense:
SELECT items.* FROM items WHERE items.id not in (Select id from sort_order)
UNION
SELECT items.* FROM items INNER JOIN sort_order ON items._id = sort_order.item_id AND sort_order.entity_id=14 WHERE (items.group_id=0 OR items.group_id=14) AND sort_order.sort >= 0
Found the source of the slow query: I forgot to create an index containing both sort_order.item_id and sort_order.item_id.
Adding a combined index did the trick for me:
CREATE INDEX sort_order_item_group
ON sort_order (order_id, group_id);

Sqlite double left outer join with count

I have the following DB structure:
tbl_record(_id,_id_user,...)
tbl_photo(_id,_id_record,...)
tbl_note(_id,_id_record,...)
When listing the records of a specific user while counting the number of photos a record has, I use the following query, which works fine:
SELECT tbl_record._id, COUNT(tbl_photo._id_record) AS photo_count FROM tbl_record
LEFT OUTER JOIN tbl_photo ON tbl_record._id=tbl_photo._id_record
WHERE tbl_record._id_user=? GROUP BY tbl_record._id;
Now, I'd like to do the same as above, but also count the number of notes a record has:
SELECT tbl_record._id, COUNT(tbl_photo._id_record) AS photo_count, COUNT(tbl_note._id_record) AS note_count FROM tbl_record
LEFT OUTER JOIN tbl_photo ON tbl_record._id=tbl_photo._id_record
LEFT OUTER JOIN tbl_note ON tbl_record._id=tbl_note._id_record
WHERE tbl_record._id_user=? GROUP BY tbl_record._id;
The count of the 2nd query does not work properly when a record has >0 photos & >0 notes, e.g. 3 photos & 5 photos which results in a count of 15 (3*5) for each.
Any idea how to make the 2nd query return the proper counts?
Thanks!!
You might be able to filter out duplicates by using COUNT(DISTINCT some_id), but this would be inefficient.
Better use correlated subqueries:
SELECT _id,
(SELECT COUNT(*)
FROM tbl_photo
WHERE _id_record = tbl_record._id
) AS photo_count,
(SELECT COUNT(*)
FROM tbl_note
WHERE _id_record = tbl_record._id
) AS note_count
FROM tbl_record
WHERE _id_user = ?

Resources