I have one table in SQL in this form:
id Name Date
----------------------------
1 john 04/05/2014
2 andi 12/05/2014
3 mark 05/08/2014
4 sofie 05/11/2014
5 john 12/12/2014
5 mark 15/12/2014
and i want to select data in this form "distinct"
id Name Date
---------------------------
1 john 12/12/2014
2 mark 15/12/2014
3 andi 12/05/2014
try something like:
SELECT t1.*
FROM <table_name> t1
WHERE t1.date = (SELECT MAX(t2.date)
FROM <table_name> t2
WHERE t2.name = t1.name)
Try this:
-- sample data
create table #tbl (id int, name nvarchar(20), [date] date);
insert into #tbl (id, name, [date]) values
(1, 'john', '2014-05-04'),
(2, 'andi', '2014-05-12'),
(3, 'mark', '2014-08-05'),
(4, 'sofie', '2014-11-05'),
(5, 'john', '2014-12-12'),
(5, 'mark', '2014-12-15');
-- solution
with ranked as
(
select id, name, [date]
, row_number() over(partition by name order by datediff(day, [date], getdate())) [rank]
from #tbl
)
select id, name, [date] from ranked where [rank] = 1;
-- cleanup
drop table #tbl;
Result
ID NAME DATE
----------------------
2 andi 2014-05-12
5 john 2014-12-12
5 mark 2014-12-15
4 sofie 2014-11-05
This solution ranks original dataset by name and in case when there are the same names ranks them by count of days between today and [date]. So the result dataset consists of rows with the unique names and the rows with names which [date] is closest to today.
Check SQLFiddle
Looks like you may want
SELECT name, MAX(date)
FROM table
GROUP BY name
However, from your example it's impossible to infer on what criterion you'd exclude sofie (and what does a duplicate id mean in your example table -- id is normally used to denote a unique identifier).
Related
Table 1:
ID
Name
Class
Date
Intime
Outtime
INAM
OUTPM
1
Smith
1st
07-12-2022
8:30 AM
Null
P
Null
1
Smith
1st
07-12-2022
Null
4:30 PM
Null
P
How to join these two rows into a single row?
Required output:
ID
Name
Class
Date
Intime
Outtime
INAM
OUTPM
1
Smith
1st
07-12-2022
8:30 AM
4:30 PM
P
P
Can someone please help me to join into a single row? Thank you...
You may aggregate by the first 4 columns and take the max of the final 4 columns:
SELECT ID, Name, Class, Date,
MAX(Intime) AS Intime, MAX(Outtime) AS Outtime, MAX(INAM) AS INAM,
MAX(OUTPM) AS OUTPM
FROM yourTable
GROUP BY ID, Name, Class, Date;
SELECT
FK,
MAX(Field1) AS Field1,
MAX(Field2) AS Field2
FROM
table1
GROUP BY
FK;
I used MAX, but any aggregate which picks one value from among the GROUP BY rows should work.
Test data:
CREATE TABLE table1 (FK int, Field1 varchar(10), Field2 varchar(10));
INSERT INTO table1 VALUES (3, 'ABC', NULL);
INSERT INTO table1 VALUES (3, NULL, 'DEF');
INSERT INTO table1 VALUES (4, 'GHI', NULL);
INSERT INTO table1 VALUES (4, 'JKL', 'MNO');
INSERT INTO table1 VALUES (4, NULL, 'PQR');
Results:
FK Field1 Field2
-- ------ ------
3 ABC DEF
4 JKL PQR
This question already has answers here:
Is there a way to access the "previous row" value in a SELECT statement?
(9 answers)
Closed 4 months ago.
Lets say I have a table like this;
Id
Name
1
John
2
Doe
5
Rose
11
Michael
15
Pedro
and my select query like this;
Id
Name
1
John
5
Rose
I want to select next rows according to my query which like this;
Id
Name
2
Doe
11
Michael
1 Johns next row is 2 Doe and 5 Roes's next row 11 Michael
One of many ways to do this:
WITH
RowNumbers AS (
SELECT
*,
ROW_NUMBER() OVER (ORDER BY ID) AS RowNumber
FROM
TableName -- replace with your table name
)
SELECT
Id,
Name
FROM
RowNumbers
WHERE
RowNumber IN (
SELECT
RowNumber+1
FROM
RowNumbers
WHERE
Name IN ('John', 'Rose')
)
;
You could use a CTE to create row_numbers and then select and join to it.
create table my_data (
id integer,
name varchar(20)
);
insert into my_data (id, name) values
(1, 'john'),
(2, 'doe'),
(5, 'rose'),
(11, 'michael'),
(15, 'pedro');
with row_data as (
select id, name,
row_number() over (order by id) as rn
from my_data
)
select b.id, b.name
from row_data a
join row_data b
on a.rn + 1 = b.rn
where a.name in ('john','rose')
id
name
2
doe
11
michael
fiddle
I got a data like it :
id date_ type
1 05/03/2020 A
2 07/03/2020 A
3 15/03/2020 A
4 25/03/2020 B
5 24/03/2020 B
6 31/03/2020 C
7 31/03/2020 D
I used the function last_day,
I did it :
select last_day(date_) from table1
But I got it :
31/03/2020 : 7
And I want to have it :
31/03/2020 : 2
thanks !
If you are looking for the count of records having last day of the month in date_ field then:
Schema and insert statements:
create table table1(id int, date_ date, type varchar(10));
insert into table1 values(1, '05-Mar-2020', 'A');
insert into table1 values(2, '07-Mar-2020', 'A');
insert into table1 values(3, '15-Mar-2020', 'A');
insert into table1 values(4, '25-Mar-2020', 'B');
insert into table1 values(5, '24-Mar-2020', 'B');
insert into table1 values(6, '31-Mar-2020', 'C');
insert into table1 values(7, '31-Mar-2020', 'D');
Query:
select date_, count(*)cnt
from table1
where date_ = last_day(date_)
group by date_;
Ouput:
DATE_
CNT
31-MAR-20
2
If you need all the date_ with count no need to use last_day:
Query:
select date_, count(*)cnt
from table1
group by date_
order by date_;
Output:
DATE_
CNT
05-MAR-20
1
07-MAR-20
1
15-MAR-20
1
24-MAR-20
1
25-MAR-20
1
31-MAR-20
2
db<>fiddle here
I think you want aggregation:
select date_, count(*)
from t
where date_ = last_day(date_)
group by date_;
The way I understood it, "last day" isn't the result of the LAST_DAY function, but maximum date value in that table. The result you're after is count of rows whose date is equal to that "maximum" date.
If that's so, then this might be one option: counting rows is easy. ROW_NUMBER analytic function calculates ordinal numbers of each row, sorted by date in descending order which means that it is the 1st row you need.
Something like this:
SQL> select date_, cnt
2 from (select date_,
3 count(*) cnt,
4 row_number() over (order by date_ desc) rn
5 from table1
6 group by date_
7 )
8 where rn = 1;
DATE_ CNT
---------- ----------
31/03/2020 2
SQL>
i have 2 sql tables
has Id, date, boolean value
has Id, date
so table 1 looks like this
1 3/1/2017 false
2 3/1/2017 true
1 1/1/2017 false
2 10/12/2016 false
table 2 like this
1 3/1/2017
2 3/1/2017
1 2/1/2017
1 12/12/2016
The result I want is for each pair of dates in table 1 that have the same id and are following each other for example for id 1 it is 1/1/2017 and 3/1/2017
to find if there is a date in table 2 with the same id that is between those dates (same day inclusive) and the boolean is false.
so for example the result in this case would be
for id1 2/1/2017, 3/1/2017
How can I do this?
How many rows there can be in Table1 with the same ID? I assume 2, but the query will work reasonably even with 1 or 3+.
"are following each other" - any two dates will follow each other, unless they are the same, so the only real check below is for inequality.
"the boolean is false" - there are two rows, which can have different boolean values. I assume both of them have to be false. (false is 0, true is 1)
Sample data
This is how your sample data should be presented in your question. At least you should write dates in a way that we don't have to guess what is month and what is day.
DECLARE #Table1 TABLE (ID int, dt date, Flag bit);
INSERT INTO #Table1 (ID, dt, Flag) VALUES
(1, '2017-01-03', 'false'),
(2, '2017-01-03', 'true'),
(1, '2017-01-01', 'false'),
(2, '2016-12-10', 'false');
DECLARE #Table2 TABLE (ID int, dt date);
INSERT INTO #Table2 (ID, dt) VALUES
(1, '2017-01-03'),
(2, '2017-01-03'),
(1, '2017-01-02'),
(1, '2016-12-12');
Query
WITH
CTE
AS
(
SELECT
ID
,MIN(dt) AS StartDT
,MAX(dt) AS EndDT
,MAX(CAST(Flag AS int)) AS MaxFlag
FROM #Table1 AS Table1
GROUP BY ID
)
SELECT
CTE.ID
,A.dt
FROM
CTE
CROSS APPLY
(
SELECT
Table2.dt
FROM #Table2 AS Table2
WHERE
Table2.ID = CTE.ID
AND Table2.dt >= CTE.StartDT
AND Table2.dt <= CTE.EndDT
) AS A
WHERE
StartDT < EndDT -- "are following each other"
AND MaxFlag = 0 -- "the boolean is false" for both IDs
;
Result
+----+------------+
| ID | dt |
+----+------------+
| 1 | 2017-01-02 |
| 1 | 2017-01-03 |
+----+------------+
Index on Table2 on (ID, dt) will help a lot.
I want to be able to identify the distinct values including a count of the value for each column in a table.
I reviewed - Get distinct records with counts
And it shows me how to do this for an individual column and works great. However, I have a table with over 600 columns, and coding each column would be incredibly time consuming.
Is there a way to code my sql where I could get these same results for all columns in a table, without having to individually input each column?
So to use the example from the link:
personid, msg
-------------
1, 'msg1'
2, 'msg2'
2, 'msg3'
3, 'msg4'
1, 'msg2'
My results would be:
personid, count | msg, count
-----------------------------
1, 2 | msg1, 1
2, 2 | msg2, 2
3, 1 | msg3, 1
_, _ | msg4, 1
Is this possible? I've tried getting at it using distincts and wildcards (*) but no luck.
Apologize if this isn't detailed enough, this is my first post and I'm no SQL expert, and Googling hasn't found an answer. Thanks.
I am not sure that it convinient, but you can do it like this:
CREATE TABLE #temp (
personid int,
message nvarchar(max)
);
GO
INSERT INTO #temp
SELECT 1, 'msg1' UNION ALL
SELECT 2, 'msg2' UNION ALL
SELECT 2, 'msg3' UNION ALL
SELECT 3, 'msg4' UNION ALL
SELECT 1, 'msg2';
GO
SELECT
isnull(t1.rn, t2.rn) as rn,
t1.personid as personid, t1.cnt as personid_cnt,
t2.message as message, t2.cnt as message_cnt
FROM
(SELECT personid, count(*) as cnt,
ROW_NUMBER() over (order by personid) as rn
FROM #temp GROUP BY personid) t1
FULL JOIN
(SELECT message, count(*) as cnt,
ROW_NUMBER() over (order by message) as rn
FROM #temp GROUP BY message) t2
ON t1.rn = t2.rn
ORDER BY rn
DROP table #temp;
result:
rn personid personid_cnt message message_cnt
1 1 2 msg1 1
2 2 2 msg2 2
3 3 1 msg3 1
4 NULL NULL msg4 1