Adding count in select query - sql

I am trying to find a query that would give me a count of another table in the query. The problem is that I have no idea what to set where in the count part to. As it is now it will just give back a count of all the values in that table.
Select
ID as Num,
(select Count(*) from TASK where ID=ID(Also tried Num)) as Total
from ORDER
The goal is to have a result that reads like
Num Total
_________________
1 13
2 5
3 22

You need table aliases. So I think you want:
Select ID as Num,
(select Count(*) from TASK t where t.ID = o.ID) as Total
from ORDER o;
By the way, ORDER is a terrible name for a table because it is a reserved work in SQL.

You can do it as a sub query or a join (or an OVER statement.)
I think the join is clearest when you are first learning SQL
Select
ID as Num, count(TASK.ID) AS Total
from ORDER
left join TASK ON ORDER.ID=TASK.ID
GROUP BY ORDER.ID

Related

Oracle SQL how to find count less than avg

my code is like :
SELECT
number,
name,
count(*) as "the number of correct answer"
FROM
table1 NATURAL JOIN table2
WHERE
answer = 'T'
GROUP BY
number,
name
HAVING
count(*) < avg(count(*))
ORDER BY
count(*);
Here I want to find the group with count less than the average number of count for each group, but here I failed to use HAVING or WHERE, could anyone help me?
How can I only select the 1 name1 2 since avg of count is (2+6+7)/3 = 5 and only 2 is less than avg.
number name count
1 name1 2
2 name2 6
3 name3 7
I would advise you to never use natural joins. They obfuscate the query and make the query a maintenance nightmore.
You can use window functions:
SELECT t.*
FROM (SELECT number, name,
COUNT(*) as num_correct,
AVG(COUNT(*)) OVER () as avg_num_correct
FROM table1 JOIN
table2
USING (?). -- be explicit about the column name
WHERE answer = 'T'
GROUP BY number, name
) t
WHERE num_correct < avg_num_correct;
As with your version of the query, this filters out all groups that have no correct answers.
I would place your current query logic into a CTE, and then tag on the average count in the process:
WITH cte AS (
SELECT number, name, COUNT(*) AS cnt,
AVG(COUNT(*)) OVER () AS avg_cnt
FROM table1
NATURAL JOIN table2
WHERE answer = 'T'
GROUP BY number, name
)
SELECT number, name, cnt AS count
FROM cte
WHERE cnt < avg_cnt;
Here we are using the AVG() function as an analytic function, with the window being the entire aggregated table. This means it will find the average of the counts per group, across all groups (after aggregation). Window functions (almost) always evaluate last.

Getting result basis on count of another SQL query

I have a table with the following columns:
bkng_date
bkng_id (varchar)
villa_id (varchar)
This query
select bkng_date,count(*) as cnt
from tab_bkng_det
group by bkng_date;
returns the no.of records for each date as count.
Now I need to find dates in the resultset of this query where cnt = 2.
I tried a couple of subqueries but I'm not getting the desired results.
The simplest, correct and safe solution is adding having count(*) = 2 clause as Gordon said.
For completeness, if you were curious how to solve it using subqueries (you didn't provide your db vendor though it's very likely your vendor supports having clause), it would be:
select x.bkng_date, x.cnt from (
select bkng_date,count(*) as cnt
from tab_bkng_det
group by bkng_date
) x
where x.cnt = 2
or
with x as (
select bkng_date,count(*) as cnt
from tab_bkng_det
group by bkng_date
)
select * from x where cnt = 2
Best Option is to use the Having Clause as follows,
select bkng_date,count(*) as cnt
from tab_bkng_det
group by bkng_date
having count(*) = 2

SQL Oracle Find Max of count

I have this table called item:
| PERSON_id | ITEM_id |
|------------------|----------------|
|------CP2---------|-----A03--------|
|------CP2---------|-----A02--------|
|------HB3---------|-----A02--------|
|------BW4---------|-----A01--------|
I need an SQL statement that would output the person with the most Items. Not really sure where to start either.
I advice you to use inner query for this purpose. the inner query is going to include group by and order by statement. and outer query will select the first statement which has the most items.
SELECT * FROM
(
SELECT PERSON_ID, COUNT(*) FROM TABLE1
GROUP BY PERSON_ID
ORDER BY 2 DESC
)
WHERE ROWNUM = 1
here is the fiddler link : http://sqlfiddle.com/#!4/4c4228/5
Locating the maximum of an aggregated column requires more than a single calculation, so here you can use a "common table expression" (cte) to hold the result and then re-use that result in a where clause:
with cte as (
select
person_id
, count(item_id) count_items
from mytable
group by
person_id
)
select
*
from cte
where count_items = (select max(count_items) from cte)
Note, if more than one person shares the same maximum count; more than one row will be returned bu this query.

group by in sql

Here i dont want to group by on amount and i also dont want to remove amount from select statement
so how to modify query
select min(id),userid,calcu.amount from usertable ut
inner join calcu co on ut.userid=co.userid
group by userid,amount
how i modify above query ...
i try to achieved records which user have min id.. let say user have 1,2,3,4 id in calcu table now i want 1 id and against that there is amount column so i want that amount ..
when i remove amount i got 10 records but when i write amount column in select and group by i got 15 records
You can achieve it using the following nested query.
SELECT (SELECT MIN(ID),USERID FROM USERTABLE ut WHERE ut.USERID = co.USERID GROUP BY USERID), co.AMOUNT FROM CALCU co
Can you try this please? Your question is not very clear (pls post sample data and a table with desired output so I can test my query)
SELECT A.MINID, A.USERID, co.AMOUNT
FROM (SELECT MIN(id) AS MINID, USERID
FROM usertable ut
GROUP BY userid
) A
INNER JOIN calcu co ON A.USERID=co.userid
When you just select amount without grouping by it, a random row for each group will be selected (if your DBMS allows this at all).
In most DBMSs you have to specify which row for each group you want to display. This happens with aggregate functions. Choose the one that fits your needs
max()
min()
avg()
count()
If you want to see the row that corresponds to a row with a min()/max() value you can use one of these approaches (they are standard sql, so not limited to mysql): The Rows Holding the Group-wise Maximum of a Certain Column
Try something around these lines:
select calcu.id,ut.userid,calcu.amount
from usertable ut
inner join
(
select id,userid,amount from calc where id in
(
select min(id) from calc group by userid
)
) calcu
on ut.userid = calcu.userid

adding count( ) column on each row

I'm not sure if this is even a good question or not.
I have a complex query with lot's of unions that searches multiple tables for a certain keyword (user input). All tables in which there is searched are related to the table book.
There is paging on the resultset using LIMIT, so there's always a maximum of 10 results that get withdrawn.
I want an extra column in the resultset displaying the total amount of results found however. I do not want to do this using a separate query. Is it possible to add a count() column to the resultset that counts every result found?
the output would look like this:
ID Title Author Count(...)
1 book_1 auth_1 23
2 book_2 auth_2 23
4 book_4 auth_.. 23
...
Thanks!
This won't add the count to each row, but one way to get the total count without running a second query is to run your first query using the SQL_CALC_FOUND_ROWS option and then select FOUND_ROWS(). This is sometimes useful if you want to know how many total results there are so you can calculate the page count.
Example:
select SQL_CALC_FOUND_ROWS ID, Title, Author
from yourtable
limit 0, 10;
SELECT FOUND_ROWS();
From the manual:
http://dev.mysql.com/doc/refman/5.1/en/information-functions.html#function_found-rows
The usual way of counting in a query is to group on the fields that are returned:
select ID, Title, Author, count(*) as Cnt
from ...
group by ID, Title, Author
order by Title
limit 1, 10
The Cnt column will contain the number of records in each group, i.e. for each title.
Regarding second query:
select tbl.id, tbl.title, tbl.author, x.cnt
from tbl
cross join (select count(*) as cnt from tbl) as x
If you will not join to other table(s):
select tbl.id, tbl.title, tbl.author, x.cnt
from tbl, (select count(*) as cnt from tbl) as x
My Solution:
SELECT COUNT(1) over(partition BY text) totalRecordNumber
FROM (SELECT 'a' text, id_consult_req
FROM consult_req cr);
If your problem is simply the speed/cost of doing a second (complex) query I would suggest you simply select the resultset into a hash-table and then count the rows from there while returning, or even more efficiently use the rowcount of the previous resultset, then you do not even have to recount
This will add the total count on each row:
select count(*) over (order by (select 1)) as Cnt,*
from yourtable
Here is your answare:
SELECT *, #cnt count_rows FROM (
SELECT *, (#cnt := #cnt + 1) row_number FROM your_table
CROSS JOIN (SELECT #cnt := 0 AS variable) t
) t;
You simply cannot do this, you'll have to use a second query.