SQL: Count (*) WHERE multiple matches are expected - sql

The query I wish to build is the following:
find all video matching categoryId field
find history records for each of them
and finally to count/sum them together.
The query I managed to build so far is:
(SELECT COUNT(*)
FROM "histories" as "history"
WHERE "history"."videoId" =
(SELECT "id"
FROM "videos"
WHERE "videos"."categoryId" = '9f5a0e6f-512b-425a-9225-600f876c0105' ))
I guess you can clearly see through where the problem is already. I'm selecting all records, where videoId is equal to... a list of ids. SQL doesn't buy it.
SQL ERROR: more than one row returned by a subquery used as an expression
The "workaround" I've found was to limit the video rows to just one. But of course, that wouldn't give me a full output.
I'll highly appreciate all the tips, or maybe even answers.

You just need to change the = operator to IN:
(SELECT COUNT(*)
FROM "histories" as "history"
WHERE "history"."videoId" IN
(SELECT "id"
FROM "videos"
WHERE "videos"."categoryId" = '9f5a0e6f-512b-425a-9225-600f876c0105' ))

I just want to note that you can also use = any:
SELECT COUNT(*)
FROM "histories" as h
WHERE h."videoId" = ANY (SELECT v."id"
FROM "videos" v
WHERE v."categoryId" = '9f5a0e6f-512b-425a-9225-600f876c0105'
);
I would strongly advise you to dispense with the double quotes around identifiers. They just clutter queries.

Related

SQL Get sum of a column from another table by ID

very inexperienced with SQL, and I've found myself needing to write a query. Hopefully you can help me understand how I'd go about this:
I have two tables.
"table_requests" contains all requests, some of which are batches
"table_pages" contains information for each page of a batch, connects to
"table_requests" on the column "table_request_id"
In addition, "table_pages" has a numeric column "word_count" that lists a number for each page and a "table_request_id" column that can match to the PK of "table_requests".
For my query, I'd like to connect "table_requests" to "table_pages" on that matching column, and select everything from "table_requests" with an added column on the end that totals the "word_count" for each "table_request" (from all pages in "table_pages").
So far I have:
select tr.id, tr.creation_date, sum(tp.word_count) as total_wc
from table_requests tr
join table_pages cp on tp.table_request_id = tr.id
Thank you all, let me know if there is any more information I can provide!
I think that the simplest approach is a correlated subquery:
select
tr.*,
(
select sum(tp.word_count)
from table_pages tp
where tp.table_request_id = tr.id
) total_wc
from table_requests tr
For performance with this query, make sure that you have an index on table_pages(table_request_id ).

sql query result returns asterisk "*" as column value

I'm trying to update a temporary table with multiple values from another table without using a join.
However, the query doesn't give any error but rather returns an asterisk as the value of the column. I have googled and asked some folks around the office but no one seems to have encountered this before or can offer explanation of why this could be happening.
update ##tempCLUnique set Total =
(
select COUNT(distinct u.unique_subs)
from tbl_Cluster_Cumm_Unique_Subs u
where u.cluster = ##tempCLUnique.cluster
)
Seems simple enough
Result Screen Grabhttp://i.stack.imgur.com/qE0ER.png
Use this
update ##tempCLUnique set Total = U.unique_subs
FROM ##tempCLUnique
INNER JOIN
(
select COUNT(distinct unique_subs)unique_subs
from tbl_Cluster_Cumm_Unique_Subs
)U
ON
u.cluster = ##tempCLUnique.cluster
Change the join according to your use.
Ashutosh

Query returning nothing

My query is as follows:
Select h.ord_no
from sales_history_header h
INNER JOIN sales_history_detail d
ON d.NUMBER = h.NUMBER
WHERE d.COMMENTS LIKE '%3838CS%'
And I get no results as shown here :
But I should get results because :
I ran the query:
Select NUMBER, Comments from SALES_HISTORY_DETAIL WHERE NUMBER LIKE '%0000125199%'
and got this (As you can see there's a comment field with 3838CS contained in it) :
And ran this query:
Select NUMBER, Ord_No from "SALES_HISTORY_HEADER" WHERE NUMBER = '0000125199'
and got this (The Ord_No exists) :
How come my first original query returns no results? Do I have the syntax wrong ?
Your query is returning nothing because the execution engine is using an index that is incorrectly referenced by this specific application (Sage BusinessVision) you have to work around the issue.
Explanation:
The issue you are having is related to the way BusinessVision created the index index of the table SALES_HISTORY_DETAIL. The PK (index key0) for this table is on both column NUMBER and RECNO.
Details on Pervasive indexs for BusinessVision
Here is the explanation of the way that index works with BV:
If you run a query that is capabable of using an index you will get better performance. Unfortunately the way pervasive compute this index for NUMBER is not working on its own.
--wrong way for this table
Select * from SALES_HISTORY_DETAIL WHERE NUMBER = '0000125199'
--return no result
Because of the way pervasive handle the index you should get no results. The workaround is you have to query on all the fields of the PK for it to work. In this case RECNO represent a record from 1 to 999 so we can specify all records with RECNO > 0.
--right way to use index key0
Select * from SALES_HISTORY_DETAIL WHERE NUMBER = '0000125199' and RECNO > 0
This will give you the result you expected for that table and use the index with the performance gain.
Note that you will get the same behavior in the table SALES_ORDER_DETAIL
Back you your question.
The query you ran to see the details did execute a table scan instead of using the index.
--the way you used in your question
Select * from SALES_HISTORY_DETAIL WHERE NUMBER LIKE '%0000125199%'
in that case it working, not because of the Like keyword but because of the leading '%'; remove it and that query won't work since the engine will optimise by using the weird index.
In your original query because you are referencing d.NUMBER = h.NUMBER pervasive use the index and you don't get any result, to fix that query simply add (and RECNO > 0)
Select h.ord_no
from sales_history_header h
INNER JOIN sales_history_detail d
ON d.NUMBER = h.NUMBER and RECNO > 0
WHERE d.COMMENTS LIKE '%3838CS%'
sage-businessvision pervasive-sql
I think this is because you have different data type for number in both table
There is no issues with your query. Looks like a data issue. "Number" stored in SALES_HISTORY_DETAIL might have some space. Its hard to tell if there is some space in value from the SS.
Run the following query to see if your SALES_HISTORY_DETAIL table number value is stored correctly.
Select NUMBER, Comments from SALES_HISTORY_DETAIL WHERE NUMBER = '0000125199'
comment column is text ? did you try
Select h.ord_no
from sales_history_header h
INNER JOIN sales_history_detail d ON d.NUMBER = h.NUMBER
WHERE cast(d.COMMENTS as varchar(max) LIKE '%3838CS%'

In an EXISTS can my JOIN ON use a value from the original select

I have an order system. Users with can be attached to different orders as a type of different user. They can download documents associated with an order. Documents are only given to certain types of users on the order. I'm having trouble writing the query to check a user's permission to view a document and select the info about the document.
I have the following tables and (applicable) fields:
Docs: DocNo, FileNo
DocAccess: DocNo, UserTypeWithAccess
FileUsers: FileNo, UserType, UserNo
I have the following query:
SELECT Docs.*
FROM Docs
WHERE DocNo = 1000
AND EXISTS (
SELECT * FROM DocAccess
LEFT JOIN FileUsers
ON FileUsers.UserType = DocAccess.UserTypeWithAccess
AND FileUsers.FileNo = Docs.FileNo /* Errors here */
WHERE DocAccess.UserNo = 2000 )
The trouble is that in the Exists Select, it does not recognize Docs (at Docs.FileNo) as a valid table. If I move the second on argument to the where clause it works, but I would rather limit the initial join rather than filter them out after the fact.
I can get around this a couple ways, but this seems like it would be best. Anything I'm missing here? Or is it simply not allowed?
I think this is a limitation of your database engine. In most databases, docs would be in scope for the entire subquery -- including both the where and in clauses.
However, you do not need to worry about where you put the particular clause. SQL is a descriptive language, not a procedural language. The purpose of SQL is to describe the output. The SQL engine, parser, and compiler should be choosing the most optimal execution path. Not always true. But, move the condition to the where clause and don't worry about it.
I am not clear why do you need to join with FileUsers at all in your subquery?
What is the purpose and idea of the query (in plain English)?
In any case, if you do need to join with FileUsers then I suggest to use the inner join and move second filter to the WHERE condition. I don't think you can use it in JOIN condition in subquery - at least I've never seen it used this way before. I believe you can only correlate through WHERE clause.
You have to use aliases to get this working:
SELECT
doc.*
FROM
Docs doc
WHERE
doc.DocNo = 1000
AND EXISTS (
SELECT
*
FROM
DocAccess acc
LEFT OUTER JOIN
FileUsers usr
ON
usr.UserType = acc.UserTypeWithAccess
AND usr.FileNo = doc.FileNo
WHERE
acc.UserNo = 2000
)
This also makes it more clear which table each field belongs to (think about using the same table twice or more in the same query with different aliases).
If you would only like to limit the output to one row you can use TOP 1:
SELECT TOP 1
doc.*
FROM
Docs doc
INNER JOIN
FileUsers usr
ON
usr.FileNo = doc.FileNo
INNER JOIN
DocAccess acc
ON
acc.UserTypeWithAccess = usr.UserType
WHERE
doc.DocNo = 1000
AND acc.UserNo = 2000
Of course the second query works a bit different than the first one (both JOINS are INNER). Depeding on your data model you might even leave the TOP 1 out of that query.

SQL queries with views and subqueries

select nid, avg, std from sView1
where sid = 4891
and nid in (select distinct nid from tblref where rid = 799)
and oidin (select distinct oid from tblref where rid = 799)
and anscount > 3
This is a query I'm currently trying to run. And running it like this takes about 3-4 seconds. However, if I replace the "4891" value with a subquery saying (select distinct sid from tblref where rid = 799) the procedure just hangs, even though the subquery only returns one sid.
The query is supposed to return a dataset with averages (avg) and standard deviations (std) over a resultset which is calculated through nested views in sView1. This dataset is then run through another view to get some top-level averages and stdevs.
The averages may need to include more than 1 sid (sid identifies a dataset).
It's difficult describing it more without revealing codebase and codestructure that shouldn't be revealed ;)
Can anyone suggest why the query hangs when trying to use the subquery? (The code is rebuilt from originally using nested cursors, since I have been told that cursors are the work of the devil, and nested cursors may make me sterile)
Try this. Exists returns as soon as it finds a matching condition, select distinct will require going through the dataset and optionally sorting it to remove the duplicates.
SELECT nid,avg,std from sView1 AS SV
WHERE EXISTS (SELECT * FROM TblRef AS TR WHERE sv.sid = Tr.sid AND Sv.nid = tr.nid AND sv.oid = tr.oid AND tr.rid = 799)
AND ansCount>3
Also, it is pretty difficult to provide a meaningful answer without access to query plans and table structures. So DDL and sample data will definitely help.