query to find more than one name with different values - sql

this is my table i need more than two names will appear as out put i used count in my query, but name timur has diff company so it cant count as 1 i need count as 2
Name ID Company Name CompanyID Role Name
Ahmed 73 King & Spalding 55 Counsel
Timur 78 Chance CIS Ltd 39 Partner
Timur 78 Clifford LLP 28 Counsel
Rahail 80 Reed Smith ltd 97 Partner
out put like this
Name ID Company Name CompanyID Role Name count
Ahmed 73 King & Spalding 55 Counsel 1
Timur 78 Chance CIS Ltd 39 Partner 2
Timur 78 Clifford LLP 28 Counsel 2
Rahail 80 Reed Smith ltd 97 Partner 1

I am assuming that name and ID match each other. So in case of duplicated names for different people, I am using ID for partitioning
SELECT
*,
count(*) over (partition by ID) as [count]
FROM yourtable

Use correlated sub-query:
select t.*, (select count(*) from tablename where name = t.name) as count
from tablename t

If you're using SQL Server 2005 or above then you can use a window function to achieve this easily:
SELECT
T.Name,
T.ID,
T.CompanyName,
T.CompanyID,
T.RoleName,
COUNT(*) OVER (PARTITION BY T.Name)
FROM
My_Table T

Related

How to select students who got above average?

How to list all students who got above average grade of their group in SQL table? We have 6 group_ids so there six different average grades.
group_id student grade
1 James 85
1 Adam 96
2 Tom 56
2 Jane 89
2 Anny 90
Result:
group_id student grade
1 Adam 96
2 Jane 89
2 Anny 90
ashkufaraz's answer is closer but not quite right
select group_id,student,grade from students one where grade >
(select avg(grade) from students two where two.group_id = one.group_id)
The question is just tagged SQL, so this is an answer using standard SQL:
One option is to use a window function:
select group_id,student,grade
from (
select group_id,student,grade,
avg(grade) over (partition by group_id) as group_avg
from studends
) t
where grade > group_avg;
This has the additional benefit that you can also display the group average along with the result with no additional join or sub-select.

SQL remove and filter similar results

I have the below query which gives me a list of orders where an address comes up twice so we can double pack same orders to the same address
select * from Orders
where
address in (select address from orders group by address having count(*) = 2)
CustID StockID Address Company
-----------------------------------------------------------------
1217 23185 1 Some Road Stockton
58458 23185 1 Some Road
58459 23185 4 John St
58457 23185 4 John St
299576 23185 9 Roadway PDE Graceland
59470 23185 9 Roadway PDE Cahill Tow
97656 23185 24 Kent St
97677 23185 24 Kent St
212732 23185 23 Best Rd
226583 23185 23 Best Rd c/o John
191718 23185 98 King St
156363 23185 98 King St
121106 23185 19 Broadway
156362 23185 19 Broadway
I want the result to look like this which excludes any addresses which come up which have a company name in either of the 2 results that come up for it. Some addresses have nothing in the Company name however i want to exclude them as well if the other result for the same address contains a company name.
CustID StockID Address Company
-----------------------------------------------------------------
58459 23185 4 John St
58457 23185 4 John St
97656 23185 24 Kent St
97677 23185 24 Kent St
191718 23185 98 King St
156363 23185 98 King St
121106 23185 19 Broadway
156362 23185 19 Broadway
Hope this all makes sense and appreciate any help
Thank you!
select * from Orders o1
where
0 = (select count(*) from orders o2
where o1.address = o2.address
and company is not null)
This is a correlated sub-query which ties the main query and subquery together over address. I have assumed "empty" company is NULL, replace with <> "" if you don't use nulls.
AS #ClockWork-Muse mentions in the comments, there's a lot of things you need to consider in this scenario, pertaining to data cleanliness as well as business logic. Having said that, you can try this for your issue:
;with filtered as
(
select * from Orders
where
address in (select address from orders group by address having count(*) = 2)
)
,cte as
(select address, max(company) as max
from filtered
group by address
having max(company) = '')
select f.* from filtered f
inner join cte c on f.address = c.address
Basically, you create a CTE to identify those companies which have only blank values for Company, and then join back to the results of your query

Selecting only rows with the highest value of one field, grouped by another field

I have a table that has information structured like this:
ID Points Name School
1 123 James A
2 534 Henry B
3 56 Henry B
4 153 Chris B
5 95 Chris B
6 83 Chris B
7 421 James A
And I need to get out of a query the rows that have the same name, but only the highest points for each like this:
ID Points Name School
7 421 James A
2 534 Henry B
4 153 Chris B
Any ideas on how this could be accomplished with a query? I've spent way too much time trying to figure this out.
select name,school,max(points) from table group by name,school
That will give you the max points per name/school combination. Join it to itself if you want the ID:
select table.* from table inner join
(select name,school,max(points) as points from table group by name,school) a
on a.name = table.name and a.school = b.school and a.points = table.points
edit : sorry, this is a SQL solution...just saw the MSACCESS tag. Logic is right, but you'll need to convert to access syntax.
edit to correct the second query, missed a column inh my join
SELECT
(SELECT TOP 1 ID FROM Table
WHERE
Name = t.Name AND
School=t.School AND
Points=t.Points
) as Id, t.Name, t.Points, t.School
FROM
(SELECT Name, School, max(Points) as Points
FROM Table
GROUP BY Name, School) t

Using distinct and sum in sql server 2008

I'm trying to get the SUM(Values) for each Acct, but my issue is trying to get at least one entire row for a DISTINCT Acct with the SUM(Values).
I have some sample data for example:
Acct Values Name Street
123456789 100.20 John 66 Main Street
123456789 200.80 John 22 Main Avenue
222222222 50.25 Jane 1 Blvd
333333333 25.00 Joe 55 Test Ave
333333333 50.00 Joe 8 Douglas Road
555555555 75.00 Tim 12 Clark Ave
666666666 500.00 Tim 12 Clark Street
666666666 500.00 Tim 3 Main Rd.
My query consisted of:
SELECT DISTINCT Acct, SUM(Value) AS [TOTAL]
FROM TABLE_NAME
GROUP BY Acct
The above query gets me close to what I need, but I need the entire row.
Example below of what I am looking for:
Acct Total Name Addr1
123456789 301.00 John 66 Main Street
222222222 50.25 Jane 1 Blvd
333333333 75.00 Joe 55 Test Ave
555555555 75.00 Tim 12 Clark Ave
666666666 1000.00 Tim 12 Clark Street
Thanks.
If it does not matter what address you return, then you can apply and aggregate to the other columns:
SELECT Acct,
SUM(Value) AS [TOTAL],
max(name) name,
max(Street) addr1
FROM TABLE_NAME
GROUP BY Acct;
See SQL Fiddle with Demo
You can do this using window functions such as row_number() in most databases:
select acct, total, name, addr1
from (select t.*, row_number() over (partition by acct order by acct) as seqnum,
sum(value) over (partition by acct) as Total
from table_name
) t
where seqnum = 1;
I would use Windowing Functions (the OVER clause) to solve this.
SELECT DISTINCT
Acct
,SUM([Values]) OVER (PARTITION BY Acct) AS 'Total'
,Name
,FIRST_VALUE(Street) OVER (PARTITION BY Acct ORDER BY Street DESC) AS 'Addr1'
FROM TABLE_NAME
;
The nice thing about Windowing Functions is that you do not add things to a grouping that you do not need in your functions (e.g. SUM), instead you can focus on describing what you are looking for.
In the SQL above, we are saying we want the SUM of Values grouped by (or PARTITION BY as it is called in the OVER clause) Acct. The FIRST_VALUE allows use to return the first value of the street address. The same did not have a DATETIME column so it is hard to say what the order should be for the first value. There is also a LAST_VALUE windowing function. Assuming you do have a DATETIME column you would want to ORDER BY that column value, if not you can just pick some value like I did with Street (MAX might also be a good option then too, but having some type of DATETIME value would be the best way to do it).
Check out this SQL Fiddle: http://sqlfiddle.com/#!6/a474c/8
Here is the BOL about SUM using the OVER clause: http://msdn.microsoft.com/en-us/library/ms187810.aspx
Here is more info on FIRST_VALUE: http://blog.sqlauthority.com/2011/11/09/sql-server-introduction-to-first-_value-and-last_value-analytic-functions-introduced-in-sql-server-2012/
Here is a blog post I've done on the Windowing Functions: http://comp-phil.blogspot.com/2013/03/higher-order-functions.html

Oracle: Combining similar names together

ItemNo Name Requested Qty
850045 MICHAEL 46 1045
850045 MICHAEL JACKSON 38 834
850045 LARRY SHEARIN 22 473
850045 Michael Jackson 11 233
850045 Larry 5 84
I have a table where Requester Name is not normalized. Michael and Michael Jack are the same person. Larry and Larry Shearin are also the same person. Is there a way to combine row data so that the Requested and Qty also sum up correctly? I was thinking there might be some sort of Oracle function or analytic that would do this...
ItemNo Name Requested Qty
850045 MICHAEL JACKSON 95 2112
850045 LARRY SHEARIN 27 557
There may be another way, but this should work using UPPER and matching any firstname (without spaces) to any fullname (with a space) -- if multiple full names match, you're results will be inaccurate.
SELECT T.ItemNo,
T.Name,
T.Requested + T2.Requested Requested,
T.Qty + T2.Qty Qty
FROM (
SELECT ItemNo, UPPER(Name) as Name, SUM(Requested) Requested, SUM(Qty) Qty
FROM YourTable
WHERE Name LIKE '% %'
GROUP BY ItemNo, UPPER(Name)
) T
JOIN (
SELECT ItemNo, UPPER(Name) as Name, SUM(Requested) Requested, SUM(Qty) Qty
FROM YourTable
WHERE Name NOT LIKE '% %'
GROUP BY ItemNo, UPPER(Name)
) T2 ON T.ItemNo = T2.ItemNo AND T.Name LIKE T2.Name||' %'
Here is the SQL Fiddle.
And here are the results:
ITEMNO NAME REQUESTED QTY
850045 MICHAEL JACKSON 95 2112
850045 LARRY SHEARIN 27 557
I assume you're total (32) for Larry was mistaken above (22 + 5)?
Hope this helps.