I have following table as below:
Structure:
ArticleId INT,
Name varchar(100),
NameId INT
Sample data:
ArticleId Name NameId
----------------------------
1 a 100
2 a 100
3 a 100
2 b 200
4 a 100
1 c 300
4 g 400
1 h 500
2 h 500
3 h 500
4 h 500
I would like to get only those Names and their NameIds whom appears among all articles (ArticleId). As given above we have ArticleIds: 1,2,3,4. Names a & h pass the criteria because only them appearing in all articles. From the other hand b,c and g appears only in given articles (not for all).
In the end, the result should be:
a 100
h 500
How can I achieve that?
Using aggregation we can try:
SELECT Name, NameId
FROM yourTable
GROUP BY Name, NameId
HAVING COUNT(*) = (SELECT COUNT(DISTINCT ArticleId) FROM yourTable);
Actually, the above only works if you're certain that every article ID would appear at least once in the table. It would be much better to assert the count of articles from a table dedicated to holding aritcles, so:
SELECT Name, NameId
FROM yourTable
GROUP BY Name, NameId
HAVING COUNT(*) = (SELECT COUNT(*) FROM articles);
Related
The goal is to rank the Movies table according to quantity in the Inventory table such that for each duplicate value, it skips the subsequent value so that the next non-duplicate value remains in its rightful position. Display MovieID, Latest Title, Price, and the Rank.
WhileMovieId ‘1’ from Movies table corresponds to MovieId ‘101’ of your Movie inventory table and so on.
These are the tables
Movies
MovieId
latest title
Price
1
Breaking Dawn
200.00
2
The Proposal
185.00
3
Iron Man 2
180.00
4
Up
180.00
5
The Karate Kid
190.00
6
How to train your Dragon
190.00
7
Spiderman 3
195.00
Movie Inventory
MovieId
Quantity
101
3
105
4
107
5
108
7
110
8
111
4
And this is my attempt at the code that is showing a lot of NULL
SELECT CASE
WHEN Movies.MovieId + 100 = MovieInventory.MovieID
THEN CAST(MovieInventory.MovieID AS INT)
END AS 'MovieId',
Movies.LatestTitle, Movies.Price,
DENSE_RANK() OVER (ORDER BY Movies.MovieId DESC) AS [Rank]
FROM Movies, MovieInventory WHERE MovieInventory.MovieID IS NOT NULL
GO
This is what you need.
Notes:
You need RANK not DENSE_RANK to achieve the result you want
You need to order by Quantity
Use proper JOIN syntax, not comma , joins
Use table aliases for better readability
The foreign and primary key relationships are weird: mi.MovieID appears to be varchar but when converted to int is 100 more than m.MovieID???
The calculation in the SELECT is not accessible to the JOIN conditions
Don't use apostrophes '' to quote column names
SELECT
mi.MovieId,
m.LatestTitle,
m.Price,
RANK() OVER (ORDER BY mi.Quantity DESC) AS [Rank]
FROM Movies m
JOIN MovieInventory mi ON TRY_CAST(mi.MovieID AS int) = m.MovieID + 100;
How to select the value from the table based on category_id?
I have a table like this. Please help me.
Table A
ID Name category_id
-------------------
1 A 1
2 A 1
3 B 1
4 C 2
5 C 2
6 D 2
7 E 3
8 E 3
9 F 3
How to get the below mentioned output from table A?
ID Name category_id
--------------------
1 A 1
2 A 1
4 C 2
5 C 2
7 E 3
8 E 3
Give a row number for each row based on group by category_id and sort by ascending order of ID. Then select the rows having row number 1 and 2.
Query
;with cte as (
select [rn] = row_number() over(
partition by [category_id]
order by [ID]
), *
from [your_table_name]
)
select [ID], [Name], [category_id]
from cte
where [rn] < 3;
Kindly run this query It really help You Out.
SELECT tbl.id,tbl.name, tbl.category_id FROM TableA as tbl WHERE
tbl.name IN(SELECT tbl2.name FROM TableA tbl2 GROUP BY tbl2.name HAVING Count(tbl2.name)> 1)
Code select all category_id from TableA which has Name entries more then one. If there is single entry of any name group by category_id then such data will be excluded. In above example questioner want to eliminate those records that have single Name entity like wise category_id 1 has name entries A and B among which A has two entries and B has single entry so he want to eliminate B from result set.
There are many questions already on SO asking how to do a general max value with group by some id. However my particular case is somewhat different.
What I have is a record with a value that links to any unknown number of profiles associated (as a "team") with that record. For simplicity in the example each team has 2 profiles but the real example could have any size.
From these records I'm trying to create a leaderboard to show the max record from each unique team formation and should only show one result even if the team scored the same max value more than once.
In this example the unique teams are (1, 2) and (2, 3).
EDIT: Unique team formation means that the leaderboard should consider all records with profiles (1, 2) to be the same unique formation of a team (as a unique id if that helps) even though the same team may have been formed multiple times for different records.
In this example team (1,2) has a duplicate max record value of 1 which should ignore the duplicate.
Lets say was have 3 users:
Table: profile
profileId | name
1 | John
2 | James
3 | Mark
Then lets say there are currently the following records:
Table: record
recordId | value
1 | 1
2 | 1
3 | 2
4 | 3
And finally each record is made of the following teams described by their members:
Table: member
recordId | profileId
1 | 1
1 | 2
2 | 1
2 | 2
3 | 2
3 | 3
4 | 3
4 | 2
The final output should look like:
recordId | profileId1 | profileId2 | value
4 | 2 | 3 | 4
1 (or 2) | 1 | 2 | 0
So far I've seem something like this to do it if the group id was part of the record:
SELECT *
FROM (SELECT *,
ROW_NUMBER() OVER (PARTITION BY profileId ORDER BY value DESC) N
FROM record
) M WHERE N = 1
And this to actually get the unique tuples:
select max(r.value) as value, p1.profileId as p1, p2.profileId as p2
from record r
inner join profile p1 on p1.recordId = r.id
inner join profile p1 on p2.recordId = r.id
where p1.profileId < p2.profileId
group by p2.profileId, p2.profileId
However, I don't know how to piece it together to get the max record for each tuple of profiles.
Also, the second query isn't very scalable for any unknown number of profiles and if there is a way to do it without self joining based on the number of profiles that would be a bonus!
If someone can help me build the right query for SQL Server that would be awesome.
Thanks!
After a bunch more research and trial and error I came to the following answer that solves my problem. This query will give the top scores from each team for a 2 person team leaderboard:
SELECT * FROM
(
SELECT ROW_NUMBER() OVER (PARTITION BY m1.profileId, m2.profileId, m3.profileId ORDER BY r.value DESC) N,
m1.profileId AS m1, m2.profileId AS m2, m3.profileId AS m3, r.value, r.id
FROM record r
INNER JOIN member m1 ON m1.recordId = r.id
INNER JOIN member m2 ON m2.recordId = r.id
WHERE m1.profileId < m2.profileId
) R
where N = 1
ORDER BY value DESC;
It works by running a partition to rank all the records by team and then plucks only the record ranked 1. The where m1.profileId < m2.profileId ensures that only 1 permutation of the team is used in the results.
How do I find the unique groups that are present in my table, and display how often that type of group is used?
For example (SQL Server 2008R2)
So, I would like to find out how many times the combination of
PMI 100
RT 100
VT 100
is present in my table and for how many itemid's it is used;
These three form a group because together they are assigned to a single itemid. The same combination is assigned to id 2527 and 2529, so therefore this group is used at least twice. (usagecount = 2)
(and I want to know that for all types of groups that are appearing)
The entire dataset is quite large, about 5.000.000 records, so I'd like to avoid using a cursor.
The number of code/pct combinations per itemid varies between 1 and 6.
The values in the "code" field are not known up front, there are more than a dozen values on average
I tried using pivot, but I got stuck eventually and I also tried various combinations of GROUP-BY and counts.
Any bright ideas?
Example output:
code pct groupid usagecount
PMI 100 1 234
RT 100 1 234
VT 100 1 234
CD 5 2 567
PMI 100 2 567
VT 100 2 567
PMI 100 3 123
PT 100 3 123
VT 100 3 123
RT 100 4 39
VT 100 4 39
etc
Just using a simple group:
SELECT
code
, pct
, COUNT(*)
FROM myTable
GROUP BY
code
, pct
Not too sure if that's more like what you're looking for:
select
uniqueGrp
, count(*)
from (
select distinct
itemid
from myTable
) as I
cross apply (
select
cast(code as varchar(max)) + cast(pct as varchar(max)) + '_'
from myTable
where myTable.itemid = I.itemid
order by code, pct
for xml path('')
) as x(uniqueGrp)
group by uniqueGrp
Either of these should return each combination of code and percentage with a group id for the code and the total number of instances of the code against it. You can use them for also adding the number of instances of the specific code/pct combo too for determining % contribution etc
select
distinct
t.code, t.pct, v.groupcol, v.vol
from
[tablename] t
inner join (select code, rank() over(order by count(*)) as groupcol,
count(*) as vol from [tablename] s
group by code) v on v.code=t.code
or
select
t.code, t.pct, v.groupcol, v.vol
from
(select code, pct from [tablename] group by code, pct) t
inner join (select code, rank() over(order by count(*)) as groupcol,
count(*) as vol from [tablename] s
group by code) v on v.code=t.code
Grouping by Code, and Pct should be enough I think. See the following :
select code,pct,count(p.*)
from [table] as p
group by code,pct
I'm using Microsoft SQL. I have a table that contains information stored by two different categories and a date. For example:
ID Cat1 Cat2 Date/Time Data
1 1 A 11:00 456
2 1 B 11:01 789
3 1 A 11:01 123
4 2 A 11:05 987
5 2 B 11:06 654
6 1 A 11:06 321
I want to extract one line for each unique combination of Cat1 and Cat2 and I need the line with the oldest date. In the above I want ID = 1, 2, 4, and 5.
Thanks
Have a look at row_number() on MSDN.
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY date_time, id) rn
FROM mytable
) q
WHERE rn = 1
(run the code on SQL Fiddle)
Quassnoi's answer is fine, but I'm a bit uncomfortable with how it handles dups. It seems to return based on insertion order, but I'm not sure if even that can be guaranteed? (see these two fiddles for an example where the result changes based on insertion order: dup at the end, dup at the beginning)
Plus, I kinda like staying with old-school SQL when I can, so I would do it this way (see this fiddle for how it handles dups):
select *
from my_table t1
left join my_table t2
on t1.cat1 = t2.cat1
and t1.cat2 = t2.cat2
and t1.datetime > t2.datetime
where t2.datetime is null