Sql list display duplicates - sql

I have a table with names and years.
Name Year
Adam 1960
Adam 1970
Adam 1980
Alex 1955
Alex 1956
Brian 1963
Cody 1959
.... ....
How can I list and display duplicates of names and years so that it shows 3 columns: name and 2 "year" columns to produce a result like:
Adam 1960 1970
Adam 1960 1980
Adam 1970 1980
Alex 1955 1956
Adam has 3 results so it appears as 3 different rows:
However in the case of Alex(2 results) it only shows one row.
The non-duplicate names do now appear.
It also needs to be sorted by left-most year value, and then right-most year value
Also, is there a way to do this without using "GROUP BY"?
Thanks

Basically, just join the tables using INNER JOIN.
SELECT a.Name, a.Year MinYear, b.Year MaxYEar
FROM TableName a
INNER JOIN TableName b
ON a.Name = b.Name AND a.Year < b.Year
SQLFiddle Demo

Can you try this solution:
SELECT t1.name, t1.age, t2.age FROM dbo.Table_1 AS t1
CROSS APPLY dbo.Table_1 AS t2
WHERE t1.name = t2.name
AND t1.age < t2.age

Related

SQL - Display Name ID from Consecutive Occurrences of values in a Table

I have a table created, as an example 'Table1', see below;
Name Year
John 2003
Lyla 1994
Faith 1996
John 2002
Carol 2000
Carol 1999
John 2001
Carol 2002
Lyla 1996
Lyla 1997
Carol 2001
John 2009
Based on the above table, I have summarised my findings.
Carol participated for 4 years in a row; 1999, 2000, 2001, 2002
John participated for 3 years in a row; 2001, 2002, 2003 – John also participated in 2009, but this does not count as part of the streak.
Lyla participated in 1994, 1996, 1997 but these were not three consecutive years.
Faith participated only 1 time.
What I am looking to do is write a SQL query where only the Name Id in the table are displayed where the users have participated for 3 consecutive years or more, so I should only be getting the names of only 'Carol' and 'John' based on the above.
I am not exactly sure how to write this and would hope that someone could guide me.
I have only come up with a short and basic start like the one below, but in all honesty I am not sure that is even the correct way to go about it.
Select Name From Table1
Where Year = ?
Order by Name asc
Group by Year
Assuming you have one row per person per year, you can use lag() and select distinct:
select distinct name
from (select t.*,
lag(year, 2) over (partition by name order by name) as prev2_year
from table1 t
) t
where prev2_year = year - 2;
This simply looks back two rows for each name and compares the year on that row to the year on the current row. If there are three years in a row, then that year is exactly year - 2.
You could also do this with joins, but the above probably performs better:
select distinct t1.name
from table1 t1 join
table1 t1_1
on t1.name = t1_1.name and
t1.year = t1_1.year + 1 join
table1 t1_2
on t1.name = t1_2.name and
t1.year = t1_2.year + 2;
select
n1.name,
SUM(CASE WHEN n2.year is null then 0 else 1 end)+1 YearsInRow
from Table1 n1
left join Table1 n2 on n2.name=n1.name and (n2.year=n1.year+1 )
GROUP by n1.name
HAVING SUM(CASE WHEN n2.year is null then 0 else 1 end)+1 >=3
output:
name YearsInRow
---------- -----------
Carol 4
John 3

cross reference nearest date data

I have three table ElecUser, ElecUsage, ElecEmissionFactor
ElecUser:
UserID UserName
1 Main Building
2 Staff Quarter
ElecUsage:
UserID Time Amount
1 1/7/2010 23230
1 8/10/2011 34340
1 8/1/2011 34300
1 2/3/2012 43430
1 4/2/2013 43560
1 3/2/2014 44540
2 3/6/2014 44000
ElecEmissionFactor:
Time CO2Emission
1/1/2010 0.5
1/1/2011 0.55
1/1/2012 0.56
1/1/2013 0.57
And intended outcome:
UserName Time CO2
1 2010 11615
1 2011 37752 (34340*0.55 + 34300*0.55)
1 2012 24320.8
1 2013 24829.2
1 2014 25387.8
2 2014 25080
The logic is ElecUsage.Amount * ElecEmissionFactor.
If same user and same year, add them up for the record of that year.
My query is:
SELECT ElecUser.UserName, Year([ElecUsage].[Time]), SUM((ElecEmissionFactor.CO2Emission*ElecUsage.Amount)) As CO2
FROM ElecEmissionFactor, ElecUser INNER JOIN ElecUsage ON ElecUser.UserID = ElecUsage.UserID
WHERE (((Year([ElecUsage].[Time]))>=Year([ElecEmissionFactor].[Time])))
GROUP BY ElecUser.UserName, Year([ElecUsage].[Time])
HAVING Year([ElecUsage].[Time]) = Max(Year(ElecEmissionFactor.Time));
However, this only shows the year with emission factor.
The challenge is to reference the year without emission factor to the latest year with emission factor.
Sub-query may be one of the solutions but i fail to do so.
I got stuck for a while. Hope to see your reply.
Thanks
Try something like this..
-- not tested
select T1.id, year(T1.time) as Time, sum(T1.amount*T2.co2emission) as CO2
from ElecUsage T1
left outer join ElecEmissionFactor T2 on (year(T1.time) = year(T2.time))
Group by year(T1.time), T1.id
use sub query to get the corresponding factor in this way
select T1.id,
year(T1.time) as Time,
sum(T1.amount*
(
select top 1 CO2Emission from ElecEmissionFactor T2
where year(T2.time) <= year(T1.time) order by T2.time desc
)
) as CO2
from ElecUsage T1
Group by year(T1.time), T1.id

sql group by find all combinations of two columns distinct values

I have following table
ORDID EMPID ITEMCOST TIME
-------------------------------------
10023 B2690 675 1992
10024 C3467 8078 1992
10025 B2690 15481 1992
10026 C5621 22884 1992
10027 B2109 30287 1992
10030 B3297 52496 1993
10031 C3467 59899 1993
10032 F5621 67302 1993
10033 G3467 74705 1993
and so on many rows.....
I am trying to find out empid who purchased some item in each and every year.
in other words want to find out empid which exist in each and every year in that table.
BTB I am using Oracle 11g Express.
Thanks in advance.
You can do this with a having clause where you compare the number of distinct years for each empid to the number of distinct years in the data:
select empid
from followingtable
group by empid
having count(distinct time) = (select count(distinct time) from followingtable);
Below query will also work.
SELECT TAB.EMPID FROM
(
SELECT A.EMPID, COUNT(DISTINCT A.TIME) YEARCOUNT FROM MY_TABLE A GROUP BY EMPID
) TAB
WHERE TAB.YEARCOUNT = (SELECT COUNT(DISTINCT B.TIME) FROM MY_TABLE B)

Retrieve all distinct records from table and if any changes happen between two similar distinct record then need to consider both. Using select query

I want to convert table1 into table2. As I need to find out all distinct records excluding mis_date fro the table and most important condition is if any changes happen between two similar distinct records than in that case I want both of them as two distinct records.
Example:
i/p
empId Empname Pancard MisDate
123 alex ads234 31/11/2012
123 alex ads234 31/12/2012
123 alex ads234 31/01/2013
123 alex dds124 29/02/2013
123 alex ads234 31/03/2013
123 alex ads234 31/04/2013
123 alex dds124 30/05/2013
Expected o/p
empId Empname Pancard MisDate
123 alex ads234 31/11/2012
123 alex dds124 29/02/2013
123 alex ads234 31/03/2013
123 alex dds124 30/05/2013
Assuming there's only one row for each MisDate (otherwise you'll have to find another way to specify ordering):
SELECT t1.empId, t1.Empname, t1.Pancard
FROM Table1 t1
LEFT OUTER JOIN Table1 t2
ON t2.MisDate = (SELECT MAX(MisDate) FROM Table1 t3 WHERE t3.MisDate < t1.MisDate)
WHERE t2.empId IS NULL
OR t2.empId <> t1.empId OR t2.Empname <> t1.Empname OR t2.Pancard <> t1.Pancard
SQL Fiddle example
This performs a self-join on the previous record, as ordered by MisDate, outputting if it is different or if there is no previous record (it is the first row).
Note: You've got some funky dates. I assume these are just transcription errors and have corrected them in the fiddle.

How to calculate the difference between values in two rows of one table using MS Access 2003 SQL? with EXTRA CRITERIA

Name ExactDate Presents
bob 2011 1
bob 2008 2
bob 2012 3
mary 1986 4
mary 2001 5
mary 2012 6
kate 2011 7
kate 2012 8
kate 2013 9
celia 2011 10
celia 1986 11
celia 1972 12
celia 2012 13
celia 1991 14
So the goal is we subtract the amount of presents kate got from celia on the same day and out put should be something like the following:
Name ExactDate Presents
celiaminuskate 2011 3
celiaminuskate 2012 5
Thank you so much I am a first time user of access and SQL . and have a data management task required of me at work. so this has really go me stuck
This is done in ms access 2003 SQL
HEY SO I GOT THE FIRST PART THERE AND NOW IT GETS HARDER ASSUMING THE DATA SET IS NOW LIKE THIS
Name ExactDate Presents Location
bob 2011 1 home
bob 2008 2 school
bob 2012 3 school
mary 1986 4 school
mary 2001 5 home
mary 2012 6 homw
kate 2011 7 home
kate 2012 8 home
kate 2011 9 school
celia 2011 10 school
celia 1986 11 school
celia 1972 12 home
celia 2012 14 home
celia 2012 13 school
So the goal is we subtract the amount of presents kate got from celia on the same year ( but since there are a few different present values for the same year we choose to have priority of home > school....for example celia and kate both recieves presents in 2012 but celia gets both home presents and school presents in 2012 in which case we choose her home present value to do the calculation) and out put should be something like the following:
Name ExactDate Presents
celiaminuskate 2011 3
celiaminuskate 2012 6
This should do it:
SELECT
'celiaminuskate' AS [NAME],
T1.[date] AS [EXACT DATE],
T1.presents - T2.presents AS [PRESENTS DIFF]
FROM
Some_Table T1
INNER JOIN Some_Table T2 ON
T2.[name] = 'kate' AND
T2.[date] = T1.[date]
WHERE
T1.[name] = 'celia'
ORDER BY
T1.[date]
A couple of suggestions since you're new to SQL:
Try to avoid using keywords, like "date" for column names
Your "date" column looks like a year, not a date. It should be named appropriately and you should make sure that it's the correct data type.
Since it sounds like the version of Access that you're using doesn't support the now standard JOIN syntax, here is another query which should be equivalent:
SELECT
'celiaminuskate' AS [NAME],
T1.[date] AS [EXACT DATE],
T1.presents - T2.presents AS [PRESENTS DIFF]
FROM
Some_Table T1, Some_Table T2
WHERE
T1.[name] = 'celia' AND
T2.[name] = 'kate' AND
T2.[date] = T1.[date]
ORDER BY
T1.[date]
T1 and T2 in this query are simply aliases for the tables in the FROM clause so that you can distinguish them.
If you're trying to put the results into another table then you will need this to be part of an INSERT statement. Or, with Access you might be able to use a query to generate a table as part of some wizard. I'm afraid that I don't have a copy handy to give more specifics. In any case, here is what the INSERT statement would look like:
INSERT INTO Some_New_Table (name, exactdate, presentsdiff)
SELECT ...
(The ellipsis just means to use the query as I have it up above)
You will need to do a self-join, because you are comparing rows from the same table.
Below we join table1 to itself using simular dates, but different names.
A more realistic answer would use unique row_ids instead of names.
Next we tell the database that we want only celia's rows in part1 and only kate's rows in part2.
SELECT 'celiaminuskate' AS useless_filler
, a.[date] AS whendidthishappen
, (celia.presents - kate.presents) AS outcome
FROM table1 AS kate
INNER JOIN table1 AS celia ON (a.[date] = b.[date] and a.name <> b.name)
WHERE celia.name = 'celia' and kate.name = 'kate'
Note that date is a reserved word and you will need to enclose it in square brackets []
The key to answering this is a self-join:
SELECT 'Celia - Kate' AS tag, C.ExactDate, C.Presents - K.Presents
FROM (SELECT ExactDate, Presents FROM AnonymousTable WHERE Name = 'celia') AS C
JOIN (SELECT ExactDate, Presents FROM AnonymousTable WHERE Name = 'kate') AS K
ON C.ExactDate = K.ExactDate
ORDER BY C.Date;
SELECT 'celiaminuskate', p1.exactdate, p1.presents - p2.presents
FROM presents p1 JOIN presents p2 ON p1.exactdate = p2.exactdate
WHERE p1.name = 'celia' AND p2.name = 'kate'