How to select the last / latest edited row in Sql Server 2008? - sql-server-2008

I have a table T1, which contains id and name. If the name is updated from front end, it then creates a new row with updated name, hence creating two row for the same id. I want to get the last or latest updated row from the table. Note:The table is not capturing any date or time column. Below is the example, here I have to get the latest record with name Albert Dazy. I am using Sql Server 2008
Table T1:
|---------------------|------------------|
| id | name |
|---------------------|------------------|
| abc_0011 | Albert |
|---------------------|------------------|
| abc_0011 | Dazy |
|---------------------|------------------|
| abc_0011 | Albert Dazy |
|---------------------|------------------|
I am not capturing time for the record, can it be done without datetime logic? Like, calculating the logic of time internally?

This query should give you the desired results.
;with CTE as(
select ID,name,row_number()over(partition by id order by id desc) RID
from #tmp
)
select C.ID,C.Name from CTE C JOIN (select max(RID) MRID,ID FROM CTE GROUP BY ID) T ON C.RID=T.MRID AND C.id=T.id

Related

Why does SQL query with GROUP BY produce more rows?

I have the following table:
+------+-------+--------------------------------------+
| id | rev | content |
+------+-------+--------------------------------------+
| 1 | 1 | ... |
| 2 | 1 | ... |
| 1 | 2 | ... |
| 1 | 3 | ... |
+------+-------+--------------------------------------+
When I run the following query:
SELECT id, MAX(rev) maxrev, content
FROM YourTable
GROUP BY id;
I get:
+------+----------+--------------------------------------+
| id | maxrev | content |
+------+----------+--------------------------------------+
| 1 | 3 | ... |
| 2 | 1 | ... |
+------+----------+--------------------------------------+
But if I remove the GROUP BY clause as follows:
SELECT id, MAX(rev) maxrev, content
FROM YourTable;
I get:
+------+----------+--------------------------------------+
| id | maxrev | content |
+------+----------+--------------------------------------+
| 1 | 3 | ... |
+------+----------+--------------------------------------+
This is counter-intuitive to me because of the expectation that a GROUP BY would reduce the number of results by eliminating duplicate values. However, in the above case, introduction of the GROUP BY does the opposite. Is this because of the MAX() function, and if so, how?
PS: The table is based on the SO question here: SQL select only rows with max value on a column. I was trying to understand the answer to that question, and in the process, came across the above situation.
EDIT:
I got the above results on sqlfiddle.com using its MySQL 5.6 engine, with no customization/configuration.
It is utilizing your MAX() function dependent on your GROUP BY clause. So, for your first query, you are saying: Give me the maximum rev for each id, whereas the second is just saying Give me the maximum rev in general.
Thanks to xQbert:
This does NOT mean that you are getting the row with the max rev in the latter case. It will take values from anywhere in the selection to use for your id and content fields.
You can read more about how SQL handles the GROUP BY statement here: Documentation
This because you are using a version previuos that mysql 5.7 ..these version allow the use of aggregated d function and select column not in group by ... this produce impredicatble result for the not aggregated column .. in mysql 5.7 this beahvior is not allowed ... you have an error if you in select not aggregated function not mentioned in group by
the correct sintax is obviuosly the first
SELECT id, MAX(rev) maxrev, content
FROM YourTable
GROUP BY id;
SELECT id, MAX(rev) maxrev, content FROM YourTable
GROUP BY id;
When you run this, as there are 2 distinct ids in the table you get two rows in the result, one per id with the max value. The grouping happens on the id column.
SELECT id, MAX(rev) maxrev, content
FROM YourTable;
If you remove the group by clause, you only get one row in the result corresponding to the max value in the entire table. There is no grouping by id.

Access 2007 Query to return latest date note from subquery

I have 2 tables joined by ProjectID in Access 2007. Table structure of primary table (A) is like
ProjectID | CustID
1 | 5
2 | 8
I have a secondary table (B) of notes on the ProjectID, structured like
ProjectNotesID | ProjectID | Note | CreateDate
---------------------------------------------------
1 | 1 | Note11 | 1/2/2015
2 | 1 | Note12 | 2/2/2015
3 | 2 | Note21 | 4/8/2015
4 | 2 | Note22 | 3/5/2015
I want to return all of, or part of, Table A, with the latest note of Table B, something like
ProjectID | CustID | Note | CreateDate
------------------------------------------
1 | 5 | Note12 | 2/2/2015
2 | 8 | Note21 | 4/8/2015
I can do (and have done) this with PHP & MySQL, but can't get it to work in Access 2007. I can return the ProjectID and latest Note date by the following query in Access 2007
SELECT ProjectID, Max(CreateDate) AS MaxOfCreateDate
FROM Table B
GROUP BY ProjectID;
I have tried Unique Values, etc., but can't get the results I am looking for.
Thanks!
Pete
I found an answer. First, I changed the query where I got the latest date, and instead got the max ProjectNotesID. The query is ::
SELECT ProjectID, Max(ProjectNotesID) AS MaxOfProjectNotesID
FROM Table B
GROUP BY ProjectID;
I then created a second query combining the above query and Table B, joining Query.MaxOfProjectNotesID <-> TableB.ProjectNotesID, and Query.ProjectID <-> TableB.ProjectID. The second query pulls all values from TableB.

MySQL: Selecting all rows with the same name, then updating another column for all except the higest value?

I have a problem which I'm having trouble putting the pieces together for.
The table in question houses online highscores for a game, and the in-game highscore list is getting saturated with the same name over and over again as people have aimed higher. What I'd like to do is only keep one score per name such that more users can see their name in the top scores (or rather, multiply all their scores except their highest by -1, so I keep the data but the negative scores won't be loaded).
The flow would be:
Select all of the same name from names column
Update where highscore is not the largest value in the first selection by multiplying score by -1.
Repeat for all different names.
The key problems I haven't found solutions for are selecting the names one by one without the need to type each name in, and then updating all but their top score within the selection.
Any help will be greatly appreciated!
Thanks,
TFS
Assuming your table looks like:
------------------------------------
| player_name | date | score |
------------------------------------
| Max | 01-03-2015 | 100 |
| Daniel | 27-02-2015 | 150 |
| Max | 24-02-2015 | 200 |
| Daniel | 26-02-2015 | 100 |
------------------------------------
You can do a SELECT statement with an ANY predicate containing a GROUP BY to get the highest score for each group, which in this case is the player, along with the date of that score.
SELECT
player_name, date, score AS "max_score"
FROM
highscores t1
WHERE
(t1.player_name, t1.score) = ANY(SELECT t2.player_name, max(t2.score) FROM highscores t2 GROUP BY t2.player_name);
This should give you the following result:
----------------------------------------
| player_name | date | max_score |
----------------------------------------
| Daniel | 27-02-2015 | 150 |
| Max | 24-02-2015 | 200 |
----------------------------------------
Note that if you just wanted to get the player_name and MAX(score), you could have used the simple GROUP BY subquery contained inside the ANY expression. However, since you also need the date, this won't work as SQL has no way of knowing which date from the group to include. According to the SQL standard, the SELECT may contain only columns mentioned in the GROUP BY (player_name) or expressions based on aggregate functions. Hence the you cannot include the date in a simple GROUP BY query and hope to get the result you want.

Handle dynamic missed columns in MySQL

I have a small doubt in MySQL. While loading data from one table to another table I faced one issue
first table: emp
id | name | sal | deptno | loc | referby
1 | abc | 100 | 10 | hyd | xyz
2 | mnc | 200 | 20 |chen | pqr
second table:emprefers
id | name | sal | deptno | loc | referby
Now I want to load the emp table data into the emprefers table. I wrote a query like
insert into emprefers select * from emp after
I ran the query, the data was loaded into the emprefers table like below:
id | name | sal |deptno | loc |referby
1 | abc | 100 | 10 | hyd | xyz
2 | mnc | 200 | 20 | chen | pqr
Now I ran the same query a second time. It has failed. The reason is the name column is deleted from the emp table.
I edited the query like:
insert into emprefers select id,'null'as name,sal,deptno,loc,referby from emp
After I ran the edited query again, now records are loading into the emprefers table and the data looks like:
id | name | sal |deptno | loc |referby
1 | null | 100 |10 | hyd | xyz
2 | null | 200 |20 |chen | pqr
Every time before loading the emprefers table I truncate the emprefers table data. And the emprefers table structure never changed.
Again, a third time I ran the same query again. The query has failed, the reason was that the sal and deptno columns were missing in the emp table.
I don't want to edit the query again, reason is we don't know which columns are/get deleted from the emp table.
This time we want solve the issue.
We want to load the data into the second table if the columns are available in the emp table, then load the data - otherwise we need to pass null or empty values for those columns.
Please tell me how to write a query to check if a column exist or not, and if it exists to retrieve the same column, otherwise assign null values for that column.
Rather than changing the existing query and truncating the table, it might be a better idea to make delete the whole table, make a copy of the original emp table and then insert the data into it. That way they'll always be the same.
DROP TABLE emprefers IF EXISTS
CREATE TABLE emprefers LIKE emp;
INSERT INTO emprefers SELECT * FROM emp
This statement will create the table over the fly.
CREATE TABLE databasename.emprefers SELECT * FROM databasename.emp;

Combine count rows in MySQL

I've got a table in MySQL that looks roughly like:
value | count
-------------
Fred | 7
FRED | 1
Roger | 3
roger | 1
That is, it was created with string ops outside of MySQL, so the values are case- and trailing-whitespace-sensitive.
I want it to look like:
value | count
-------------
Fred | 8
Roger | 4
That is, managed by MySQL, with value a primary key. It's not important which one (of "Fred" or "FRED") is kept.
I know how to do this in code. I also know how to generate a list of problem values (with a self-join). But I'd like to come up with a SQL update/delete to migrate my table, and I can't think of anything.
If I knew that no pair of records had variants of one value, with the same count (like ("Fred",4) and ("FRED",4)), then I think I can do it with a self-join to copy the counts, and then an update to remove the zeros. But I have no such guarantee.
Is there something simple I'm missing, or is this one of those cases where you just write a short function outside of the database?
Thanks!
As an example of how to obtain the results you are looking for with a SQL query alone:
SELECT UPPER(value) AS name, SUM(count) AS qty FROM table GROUP BY name;
If you make a new table to hold the correct values, you INSERT the above query to populate the new table as so:
INSERT INTO newtable (SELECT UPPER(value) AS name, SUM(count) AS qty FROM table GROUP BY name);
Strangely, MySQL seems to do this for you. I just tested this in MySQL 5.1.47:
create table c (value varchar(10), count int);
insert into c values ('Fred',7), ('FRED',1), ('Roger',3), ('roger',1);
select * from c;
+-------+-------+
| value | count |
+-------+-------+
| Fred | 7 |
| FRED | 1 |
| Roger | 3 |
| roger | 1 |
+-------+-------+
select value, sum(count) from c group by value;
+-------+------------+
| value | sum(count) |
+-------+------------+
| Fred | 8 |
| Roger | 4 |
+-------+------------+
I was surprised to see MySQL transform the strings like that, and I'm not sure I can explain why it did that. I was expecting to have to get four distinct rows, and to have to use some string functions to map the values to a canonical form.