Count the number of multiple values in a single column in SQL - sql-server

I have a long list of string values that I would like to count, in one particular column of a table. I know this works for counting all unique values.
SELECT
code_id ,
COUNT(*) AS num
FROM
mydb
GROUP BY
code_id
ORDER BY
code_id
I only have a certain selection of values to count, therefore do now want all. My list is long, but for example, if I just wanted to count the numbers of strings 'ax1', 'c39', and 'x1a' in my code_id column? I've seen examples with multiple lines of code, one for each value which will be huge for counting many values. I'm hoping for something like :
SELECT
code_id ,
COUNT(* = ('ax1, 'c39', 'x1a')) AS num
FROM
mydb
GROUP BY
code_id
ORDER BY
code_id
Desired output would be
code_id count
ax1 39
c39 42
x1a 0
Is there an easy way, rather than a line of code for each value to be counted?

Create a CTE that returns all the string values and a LEFT join to your table to aggregate:
WITH cte AS (SELECT code_id FROM (VALUES ('ax1'), ('c39'), ('x1a')) c(code_id))
SELECT c.code_id,
COUNT(t.code_id) AS num
FROM cte c LEFT JOIN tablename t
ON t.code_id = c.code_id
GROUP BY c.code_id;
See the demo.

I think this should work.
SELECT
code_id ,
sum(1) AS num
FROM Mydb
WHERE code_id in ('ax1', 'c39', 'x1a')
GROUP BY code_id
ORDER BY code_id

Related

Table with record occurrences count for each column in PostgreSQL

I'm looking to generate a table of columns containing count of the occurences of each unique record using PostgreSQL. My current approach is following:
with a as (SELECT count(*) as count_each_record_a
FROM (SELECT column1 as word from table_name) t
group by word),
b as (SELECT count(*) as count_each_record_b
FROM (SELECT column2 as word from table_name) t
group by word)
select * from a, b;
When I run part of the query, as in:
SELECT count(*) as count_each_record_b
FROM (SELECT column2 as word from table_name) t
group by word
then I get proper results.
When I run the whole query, I get the proper results for count_each_record_a, but column count_each_record_b is populated only with 1. Column count_each_record_b should be the same as when running the query by itself.
What am I doing wrong here?
I've actually found an answer, even if it's not that straightforward:
with a as (SELECT ARRAY(SELECT count(*)
FROM (SELECT a as word from table) t
group by word) as a),
b as (SELECT ARRAY (SELECT count(*)
FROM (SELECT b as word from table) t
group by word) as b)
select * from a, b
I get for each column one row with an array containing the occurences. Since I'm using this data further, it does serve my needs, but I would't call this a proper solution for the concept problem at hand.

Trying to get tie results on column not included in order by

Given the following result sets, sorted in descending order on column Date.
I want to use Top clause like:
select top 4 *
from donation d
order by d.Date desc;
Which give me the following result:
Even though I limit my result with top 4, I want to be able to include the last row, because it is tie with the last record (id : 5) based on the Name.
This query first selects the names of the people in the top 4 dates (in a Common Table Expression), then uses these names to shown all their data. I guess that is what you want.
;WITH Top4Names AS
(
SELECT TOP 4 [Name]
FROM donation
ORDER BY [Date] DESC
)
SELECT d.id, d.[Name], d.Amount, d.[Date]
FROM donation d
INNER JOIN Top4Names t
ON t.[Name] = d.[Name]
ORDER BY d.[Date] DESC;

Count all max number value in difference tables sql

I got an error when I tried to solve this problem. First I need to count all values of 2 tables then I need in where condition get all max values.
My code:
Select *
FROM (
select Operator.OperatoriausPavadinimas,
(
select count(*)
from Plan
where Plan.operatoriausID= Operator.operatoriausID
) as NumberOFPlans
from Operator
)a
where a.NumberOFPlans= Max(a.NumberOFPlans)
I get this error
Msg 147, Level 15, State 1, Line 19
An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING clause or a select list, and the column being aggregated is an outer reference.
I don't know how to solve this.
I need get this http://prntscr.com/p700w9
Update 1
Plan table contains of http://prntscr.com/p7055l values and
Operator table contains of http://prntscr.com/p705k0 values.
Are you looking for... an aggregate query that joins both tables and returns the record that has the maximum count?
I suspect that this might phrase as follows:
SELECT TOP(1) o.OperatoriausPavadinimas, COUNT(*)
FROM Operatorius o
INNER JOIN Planas p ON p.operatoriausID = o.operatoriausID
GROUP BY o.OperatoriausPavadinimas
ORDER BY COUNT(*) DESC
If you want to allow ties, you can use TOP(1) WITH TIES.
You can use top with ties. Your query is a bit hard to follow, but I think you want:
select top (1) with ties o.OperatoriausPavadinimas, count(*)
from plan p join
operator o
on p.operatoriausID = o.operatoriausID
group by o.OperatoriausPavadinimas
order by count(*) desc;

concatenate columns from 2 tables in resultset

Here is simplified version of my schema. Using Sql Server 2012 enterprise edition.
CREATE table #abc (a INT , b INT);
CREATE TABLE #def ( a INT , c INT ,d INT);
INSERT INTO #abc values(1,23),(1,24);
INSERT INTO #def VALUES(1,53,54),(1,56,57)
Table #abc JOINs TO #def ON COLUMN a
Basically it is concatenation of rows from both tables based on column a. Tried inner join\cross apply but they all results in cross join kind of resultset understandably . I have workaround using another temp table(then update) but kind of feel that this can be done easily in single select . I am missing something simple here.
Need output like this:
a b c d
1 23 53 54
1 24 56 57
Thanks
-N
You need some sort of sequence number to join the tables together. You can generate one using row_number() as follows:
select a.a, a.b, d.c, d.d
from (select a.*, row_number() over (order by (select NULL)) as seqnum
from #abc a
) a join
(select d.*, row_number() over (order by (select NULL)) as seqnum
from #def d
) d
on a.seqnum = d.seqnum;
Now the caution, caution, caution. The order by clause does not really specify the ordering, so the sequence numbers may not be what you expect. You should really have a column to specify the ordering.
You need to have a unique key value in each row to be able to join the tables in the way you would like. Then, an inner join will return the result set you require.
If you introduce referential integrity between the tables, then this will be enforced and return the expected results.

Converting MS ACCESS query into SQL Server query

I have the following access query which I need to run in mssql:
SELECT
[PUB_op-mstr].[om-job],
Last([PUB_op-mstr].[om-emp]) AS [LastOfom-emp],
Max([PUB_op-mstr].[om-dt-end]) AS [MaxOfom-dt-end],
[PUB_op-mstr].[om-wkctr]
FROM
PUB_wc_mstr INNER JOIN [PUB_op-mstr]
ON
PUB_wc_mstr.wc_wkctr = [PUB_op-mstr].[om-wkctr]
GROUP BY
[PUB_op-mstr].[om-job],
[PUB_op-mstr].[om-wkctr],
PUB_wc_mstr.wc_dept
HAVING
(((Max([PUB_op-mstr].[om-dt-end]))>=Date()-7
And
(Max([PUB_op-mstr].[om-dt-end]))<Date())
AND ((PUB_wc_mstr.wc_dept)="633" Or (PUB_wc_mstr.wc_dept)="646"));
MS SQL doesn't support LAST aggregate function. So, you can just replace it with Min / Max. Or you have write your own SELECT like
[LastOfom-emp] = (SELECT ...
LAST() in Access gives the last element of the column you're looking in.
Example: T1 has one column c1, which contains:
one
two
three
The statement:
SELECT LAST(c1) FROM T1
gives: three
Porting this function to SQL Server is doable, but only if there is (at least) one sorted column in the table. To get the last element of the column, you would have to do:
SELECT TOP(1) c1 FROM T1 ORDER BY c1 DESC;
This would give you the wrong result, namely "two" (because the column isn't sorted). So, to find in this case the right answer, you would need another column, for example an incrementing ID
c1 c2
one 1
two 2
three 3
Now you can:
SELECT TOP(1) c1 FROM T1 ORDER BY c2 DESC;
Since c2 is sorted, you now get the result "three".
Assuming Last([PUB_op-mstr].[om-emp]) is the om-emp value for the maximum om-dt-end, try:
select [om-job], [LastOfom-emp], [MaxOfom-dt-end], [om-wkctr] from
(SELECT [PUB_op-mstr].[om-job],
[PUB_op-mstr].[om-emp] AS [LastOfom-emp],
[PUB_op-mstr].[om-dt-end] AS [MaxOfom-dt-end],
[PUB_op-mstr].[om-wkctr],
row_number() over (partition by [PUB_op-mstr].[om-job],
[PUB_op-mstr].[om-wkctr],
PUB_wc_mstr.wc_dept
order by [PUB_op-mstr].[om-dt-end] desc) rn
FROM PUB_wc_mstr
JOIN [PUB_op-mstr]
ON PUB_wc_mstr.wc_wkctr = [PUB_op-mstr].[om-wkctr]
WHERE PUB_wc_mstr.wc_dept IN ('633','646')
) sq
where rn=1 and
[MaxOfom-dt-end]>=Dateadd(d,-7, getdate()) And
[MaxOfom-dt-end]< getdate()

Resources