repeating the same numbers in sql - sql

I have the following problem .
I want this SQL Server 2008 query
select code , name from customer
i want to have 2 or more of the same numbers appear in a separate column like this
code name repeating_numbers
x1 mike 1
x1500 George 2
x200 maria 1
x2098 john 2
a9876 mario 1
if i filter the query to show only the customers with M% i want to see
code name repeating_numbers
x1 mike 1
x200 maria 2
a9876 mario 1
if i want to see the names %o% i need to see
code name repeating_numbers
x1500 George 1
a9876 mario 2
x2098 john 1
in other words no mater the filters i need to see numbers 1,2 or maybe 3 in the future, repeat , thank you in advanced

You can use the ROW_NUMBER with the modulus operator (%):
SELECT code, name, (ROW_NUMBER() OVER (ORDER BY code ASC) - 1) % 2 + 1 AS repeating_numbers
FROM customer
The same is working with any other number too (like 3):
SELECT code, name, (ROW_NUMBER() OVER (ORDER BY code ASC) - 1) % 3 + 1 AS repeating_numbers
FROM customer
You can also use the following to avoid the ORDER BY:
SELECT code, name, (ROW_NUMBER() OVER (ORDER BY (SELECT 100)) - 1) % 2 + 1 AS repeating_numbers
FROM customer
demos: http://sqlfiddle.com/#!18/bdae7/6/1

Related

count different column values after grouping by

Consider this table:
id name department email
1 Alex IT blah#gmail.com
1 Alex IT blah#gmail.com
2 Jay HR jay#gmail.com
2 Jay Marketing zou#gmail.com
If I group byid,name and count I get:
id name count(*)
1 Alex 2
2 Jay 2
With this query:
select id,name,count(*) from tb group by id,name;
However I would like to count only records that diverge from department,email, so as to have:
id name count(*)
1 Alex 0
2 Jay 1
This time the count for the first group 1,Alex is 0 because department,email have the same values (duplicated) , on the other hand 2,Jay is one because department,email has one different value.
If you meant "two different values" for "Jay", you can use distinct:
select id,name,count(*) from (SELECT distinct * FROM tb) group by id,name;
You can use count(*) - 1 to get similar results in your question.

Take a list of names and randomly pair them off (SQL)

I'm trying to do something I thought would be fairly easy and am now on the verge of bashing my head off the desk!
I have a list of names as an array and I want to create random pairs from that list.
So I have
SELECT * FROM (
VALUES
('Angie'),
('Bob'),
('Meg'),
('Colin'),
('Debbie'),
('Eddie'),
('Fiona'),
('Gary'),
('Harriet'),
('Ian'),
('Julie'),
('Kevin'),
('Mary'),
('Noah'),
('Olivia')
) AS t (name)enter code here
and I want to get back something like
Name 1 Name2
1. Olivia Debbie
2. Gary Harriet
3. Bob Mary
4. Noah Colin
5. Ian Fiona
6. Kevin Mary
7. Julie Eddie
8. Angie NULL
Is there a way this can be achieved?
Use row_number() and aggregation:
select max(case when mod(seqnum, 2) = 1 then name end) as name1,
max(case when mod(seqnum, 2) = 0 then name end) as name2
from (select name, row_number() over (order by random()) - 1 as seqnum
from t
) t
group by floor(seqnum / 2);

Limit column value repeats to top 2

So I have this query:
SELECT
Search.USER_ID,
Search.SEARCH_TERM,
COUNT(*) AS Search.count
FROM Search
GROUP BY 1,2
ORDER BY 3 DESC
Which returns a response that looks like this:
USER_ID SEARCH_TERM count
bob dog 50
bob cat 45
sally cat 38
john mouse 30
sally turtle 10
sally lion 5
john zebra 3
john leopard 1
And my question is: How would I change the query, so that it only returns the top 2 most-searched-for-terms for any given user? So in the example above, the last row for Sally would be dropped, and the last row for John would also be dropped, leaving a total of 6 rows; 2 for each user, like so:
USER_ID SEARCH_TERM count
bob dog 50
bob cat 45
sally cat 38
john mouse 30
sally turtle 10
john zebra 3
In SQL Server, you can put the original query into a CTE, add the ROW_NUMBER() function. Then in the new main query, just add a WHERE clause to limit by the row number. Your query would look something like this:
;WITH OriginalQuery AS
(
SELECT
s.[User_id]
,s.Search_Term
,COUNT(*) AS 'count'
,ROW_NUMBER() OVER (PARTITION BY s.[USER_ID] ORDER BY COUNT(*) DESC) AS rn
FROM Search s
GROUP BY s.[User_id], s.Search_Term
)
SELECT oq.User_id
,oq.Search_Term
,oq.count
FROM OriginalQuery oq
WHERE rn <= 2
ORDER BY oq.count DESC
EDIT: I specified SQL Server as the dbms I used here, but the above should be ANSI-compliant and work in Snowflake.

SQL field default "count(another_field) +1"

I need to create a field COUNT whose default value is the automatically generated count of times NAME has appeared in that table till now, as shown in example below. Since i am adding the field to an existing table, i also need to populate existing rows. How best to go about this please?
ID NAME COUNT
1 peter 1
2 jane 1
3 peter 2
4 peter 3
5 frank 1
6 jane 2
7 peter 4
You would do this when you are querying the table, using the ANSI-standard row-number function:
select id, name, row_number() over (partition by name order by id) as seqnum
from t;

SQL Server select first instance of ranked data

I have a query that creates a result set like this:
Rank Name
1 Fred
1 John
2 Mary
2 Fred
2 Betty
3 John
4 Betty
4 Frank
I need to then select the lowest rank for each name, e.g.:
Rank Name
1 Fred
1 John
2 Mary
2 Betty
4 Frank
Can this be done within TSQL?
SELECT MIN(Rank) AS Rank, Name
FROM TableName
GROUP BY Name
yes
select name, min(rank)
from nameTable
group by name
As Paul + Kevin have pointed out, simple cases of returning a value from an aggregate can be extracted using MIN / MAX etc (just note that RANK is a reserved word)
In a more general / complicated case, e.g. where you need to find the second / Nth highest rank, you can use PARTITIONs with ROW_NUMBER() to do ranking and then filter by the rank.
SELECT [Rank], [Name]
FROM
(
SELECT [RANK], [Name],
ROW_NUMBER() OVER (PARTITION BY [Name] ORDER BY [Rank]) as [RowRank]
FROM [MyTable]
) AS [MyTableReRanked]
WHERE [RowRank] = #N
ORDER BY [Rank];