Hi I have this item about insert if not exists here. One of the things I want to know about is if I want to get the latest items from CompResults by using order by ResultDate, to be inserted to Competitors table, how should I do it?
INSERT Competitors (cName)
SELECT DISTINCT Name
FROM CompResults cr
WHERE
NOT EXISTS (SELECT * FROM Competitors c
WHERE cr.Name = c.cName) ORDER BY cr.ResultsDate DESC
An error happens: ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
Hi you have to use order by fields in select statement I think You are using sql server
so You can use sub query
INSERT Competitors (cName)
select Name
from (
SELECT cr.Name,max(cr.ResultDate)
FROM CompResults cr
WHERE NOT EXISTS (SELECT * FROM Competitors c
WHERE cr.Name = c.cName) group BY cr.name) as t order by ResultDate
Use Row_Number to get the latest record for each Item
Insert into Competitors(col1,col2..)
Select col1,col2,..
(
Select row_number()Over(partition by Name order by ResultDate desc) Rn, *
From CompResults cr
NOT EXISTS (SELECT 1 FROM Competitors c
WHERE cr.Name = c.cName)
) a
Where Rn = 1
Also you can as the below:
INSERT Competitors (cName)
SELECT
A.Name
FROM
CompResults A INNER JOIN
(
SELECT
CR.Name,
MAX(CR.ResultsDate) MaxResultsDate
FROM
CompResults CR
) B ON A.Name = B.Name AND A.ResultsDate = B.MaxResultsDate
WHERE
NOT EXISTS (SELECT 1 FROM Competitors c
WHERE c.cName = A.Name)
Related
I'm trying to insert the value '1' into column 'isTransfer' of every result of an subquery, but it's not working. This is the query where I select the rows:
select r.*
from players r
inner join (
select name, rating, max(id) id
from players group by name, rating
having count(distinct club) > 1
)
q on r.name = q.name and r.rating = q.rating and r.id = q.id
This is what I'm trying to do:
INSERT INTO 'isTransfer' VALUES '1' WHERE
(select r.*
from players r
inner join (
select name, rating, max(id) id
from players group by name, rating
having count(distinct club) > 1
)
q on r.name = q.name and r.rating = q.rating and r.id = q.id)
For this task, you need to do an UPDATE query. Also, you cannot use the WHERE clause like that, you will get an error. Instead, change the where clause to look where the primary key is returned by the subquery. It would look something like this:
UPDATE myTable
SET isTransfer = 1
WHERE primaryKey IN [mySubquery];
You need to make sure that the only column in your SELECT of the subquery is the primary key, otherwise you will get an invalid operand count error.
In regards to your query in the comments, the JOIN is not necessary. Instead, just get the distinct id values from the subquery like this:
SELECT DISTINCT id
FROM(
SELECT name, rating, MAX(id) AS id
FROM players
GROUP BY name, rating
HAVING COUNT(DISTINCT club) > 1) q
Then, but that query as your IN operand.
Assuming the id is unique in the players table:
update players r inner join
(select name, rating, max(id) as id
from players p
group by name, rating
having count(distinct club) > 1
) nr
on r.id = nr.id
set isTransfer = 1;
So I have two tables, STOPS_AT and POINT_OF_INTEREST, which are like this:
STOPS_AT[Route_ID, Stop_ID]
and
POINT_OF_INTEREST[Stop_ID, Name, Category]
Now I am trying to select the Route_ID who has the most number of stops at a point of interest. In other words, the route who has the most number of stops, who also appear in the POINT_OF_INTEREST table. I have tried the following:
select Route_ID
from (select Route_ID, count(POINT_OF_INTEREST.Stop_ID) as cnt
from STOPS_AT R
group by Route_ID
) rc join
(select max(cnt) as maxcnt
from (select Route_ID, count(POINT_OF_INTEREST.Stop_ID) as cnt
from STOPS_AT
group by Route_ID
) rc
) m
on rc.cnt = m.maxcnt;
However this doesn't seem to work, saying it is unaware of the POINT_OF_INTEREST table?
Your query doesn't join to the point_of_interest table -- that's why you're receiving the error. You are trying to count a field you are not selecting from.
If you don't need to worry about ties, one easy way would be to use limit:
select route_id
from (
select sa.route_id, count(*) cnt
from stops_at sa
join point_of_interest poi on sa.route_id = poi.route_id
group by sa.route_id
) t
order by cnt desc
limit 1
If ties are a concern, then you can alter your query using the above:
select Route_ID
from (
select sa.route_id, count(*) cnt
from stops_at sa
join point_of_interest poi on sa.route_id = poi.route_id
group by sa.route_id
) rc join
(select max(cnt) as maxcnt
from (
select sa.route_id, count(*) cnt
from stops_at sa
join point_of_interest poi on sa.route_id = poi.route_id
group by sa.route_id
) rc
) m
on rc.cnt = m.maxcnt;
The title may be confusing, here is my schema
and here is the result of my query
how can i remove duplicates and just get the values highlighted, i am trying to order by message time
Regards
The following syntax will work in both SQL Server and MySQL:
SELECT c.ContactID, c.Name, m.Text, m.Messagetime
FROM Contacts c INNER JOIN
Messages m
ON c.ContactID = m.ContactID
WHERE NOT EXISTS (select 1
from messages m2
where m2.ContactId = m.ContactId and
m2.MessageTime > m.MessageTime
)
ORDER BY m.MessageTime desc;
Note that if you have duplicate most recent message times, then all will be returned.
One way in SQL-Server is using a ranking function like ROW_NUMBER:
WITH CTE AS
(
SELECT c.ContactID, c.Name, m.Text, m.Messagetime,
RN = ROW_NUMBER() OVER (PARTITION BY c.ContactID
ORDER BY m.MessageTime DESC)
FROM dbo.Contacts c
INNER JOIN Messages m ON c.ContactID = m.ContactID
)
SELECT ContadctId, Name, Text, Messagetime
FROM CTE
WHERE RN = 1
I wrote the following query to return the the records with the latest date.
select fs.company_id, max(fs.create_dt) as latestcreatedate
from field_sale fs
group by fs.company_id
order by fs.company_id
The query all works fine. But I need to retrieve the record with all related columns attached to it. Such as, id, title, desc and etc.
How can I retrieve the records with its corresponding columns?
Couple ways of doing so :
-- 1.
SELECT a.*
FROM field_sale a
INNER JOIN
(
select fs.company_id, max(fs.create_dt) as latestcreatedate
from field_sale fs
group by fs.company_id
)b
ON b.company_id = a.company_id AND b.latestcreatedate = a.create_dt
order by a.company_id;
-- 2.
SELECT b.* FROM
(
SELECT a.* , ROW_NUMBER()
OVER (PARTITION BY a.company_id ORDER BY a.create_dt DESC)
AS rn
FROM field_sale a
)b WHERE b.rn = 1
ORDER BY company_id
WITH t AS (
SELECT fs.company_id,
fs.create_dt AS latestcreatedate,
id,
title,
etc,
ROW_NUMBER() OVER ( PARTITION BY fs.company_id ORDER BY fs.create_dt DESC ) AS rowNum
FROM field_sale fs
)
SELECT t.company_id,
t.latestcreatedate,
t.id,
t.title,
t.etc
FROM t
WHERE t.rowNum = 1
ORDER BY t.company_id
I need help writing a query to get some information but I am having trouble writing it.
[table_People]
int id
var name
[table_Tools]
int id
var name
[table_Activity1]
int person_id
int tool_id
date delivery_date
[table_Activity2]
int person_id
int tool_id
date installation_date
The query needs to return a list of all people and the name of the most recent tool they used in either activity 1 or 2 (the most recent activity that happened between the two).
SELECT
people.id AS personId,
people.name AS personName,
(
SELECT
tools.name AS toolName
FROM
activity1
JOIN
tools ON tools.id=activity1.tool_id
WHERE
activity1.id=people.id
UNION ALL
SELECT
tools.name AS toolName
FROM
activity2
JOIN
tools ON tools.id=activity2.tool_id
WHERE
activity2.id=people.id
ORDER BY
installationDate,deliveryDate
) AS toolName
FROM
people
ORDER BY
people.name
ASC
The problem I am having is that I can't sort by date (delivery or installation) as I get errors because they are different column names.
Using UNION in a subquery creates a derived temporary table. Columns that aren't selected are not in the result set, so you can't ORDER on a column that's not in the SELECT clause.
When using UNION, the first column name that is used in the SELECT clause is used in the result set (similar to an alias, though you could also use an alias).
Just be sure to name the column in the SELECT clause.
You also need a LIMIT clause to restrict the subquery to a single row:
SELECT
people.id AS personId,
people.name AS personName,
(
SELECT
tools.name AS toolName, delivery_date
FROM
activity1
JOIN
tools ON tools.id=activity1.tool_id
WHERE
activity1.id=people.id
UNION ALL
SELECT
tools.name AS toolName, installation_date
FROM
activity2
JOIN
tools ON tools.id=activity2.tool_id
WHERE
activity2.id=people.id
ORDER BY
deliveryDate
LIMIT 1
) AS toolName
FROM
people
ORDER BY
people.name
ASC
Here's a more simple example to illustrate the issue:
SELECT fish FROM sea
UNION
SELECT dog FROM land
ORDER BY fish
Is the same as:
SELECT fish AS animal FROM sea
UNION
SELECT dog AS animal FROM land
ORDER BY animal
The results are put into a derived temporary table, and you can name the columns whatever you want, but the first name that you use sticks.
My solution puts the unions together in a subquery and then orders by them. You only want the first row, so you need a limit clause (or rownum = 1 in Oracle or top 1 in MSSQL):
SELECT people.id AS personId,
people.name AS personName,
(SELECT toolname
FROM ((SELECT tools.name AS toolName, delivery_date as thedate
FROM activity1 a
WHERE a.PersonId = people.id
) union all
(SELECT tools.name AS toolName, installation_date as thedate
FROM activity2 a
WHERE a.PersonId = people.id
)
) a join
tools t
on a.toolsid = t.toolsid
order by 2 desc
limit 1
) AS toolName
FROM people
ORDER BY people.name ASC
To simplify the query, I also removed the innermost join to tools.
you cannot sort columns without specifying them after your select.
For Example:
select name from people order by name
select a1.delivery_date, t.name from activity1 a1, tools t
order by a1.delivery_date,t.name
All selected columns for the projection MUST be defined in the order by definition as well. In your example both select statements are just taking tools.name as toolname but you want to sort by other columns.
MySQL version (possibly you can get more compact code from it):
Select * from
(
Select toolName, person_id, Max(TargetDate) as MaxDate
From
(
SELECT tools.name AS toolName, activity1.person_id, activity1.delivery_date as targetDate
FROM
activity1
JOIN
tools ON tools.id=activity1.tool_id
UNION ALL
SELECT
tools.name AS toolName, activity2.person_id, activity2.installation_date as TargetDate
FROM
activity2
JOIN
tools ON tools.id=activity2.tool_id
)
Group by toolName, person_id
) preselect
join
(
Select toolName, person_id, Max(TargetDate)
From
(
SELECT tools.name AS toolName, activity1.person_id, activity1.delivery_date as targetDate
FROM
activity1
JOIN
tools ON tools.id=activity1.tool_id
UNION ALL
SELECT
tools.name AS toolName, activity2.person_id, activity2.installation_date as TargetDate
FROM
activity2
JOIN
tools ON tools.id=activity2.tool_id
)) result on result.toolName = preselect.toolName and result.person_id = preselect.person_id and result.TargetDate = preselect.MaxDate
Do
SELECT
people.id AS personId,
people.name AS personName,
IF (
(SELECT
deliveryDate AS dDate
FROM
activity1
WHERE
person_id=personId) --assuming you have only one row returned here, else limit by some condition
>
(SELECT
installationDate AS iDate
FROM
activity2
WHERE
person_id=personId) --assuming you have only one row returned here, else limit by some condition
, (SELECT
tools.name AS toolName
FROM
activity1
JOIN
tools ON tools.id=activity1.tool_id
WHERE
activity1.person_id=personId)
, (SELECT
tools.name AS toolName
FROM
activity2
JOIN
tools ON tools.id=activity2.tool_id
WHERE
activity2.person_id=personId)
) AS toolName
FROM
people
ORDER BY
people.name
ASC
This query assumes there is only record per person in activity tables. If there are more you need to limit your select result set based on sum maximum condition or so which only u know.
SELECT
p.id AS person_id
, p.name AS person_name
, CASE WHEN COALESCE(a1.delivery_date, '1000-01-01')
> COALESCE(a2.installation_date, '1000-01-01')
THEN t1.name
ELSE t2.name
END AS tool_name
FROM
People AS p
LEFT JOIN
Activity1 AS a1
ON (a1.tool_id, a1.delivery_date) =
( SELECT tool_id, delivery_date
FROM Activity1 AS a
WHERE a.person_id = p.id
ORDER BY delivery_date DESC
LIMIT 1
)
LEFT JOIN
Tools AS t1
ON t1.id = a1.tool_id
LEFT JOIN
Activity2 AS a2
ON (a2.tool_id, a2.installation_date) =
( SELECT tool_id, installation_date
FROM Activity2 AS a
WHERE a.person_id = p.id
ORDER BY installation_date DESC
LIMIT 1
)
LEFT JOIN
Tools AS t2
ON t2.id = a2.tool_id
select people.id as person_id,people.name as person_name,tools.name as toolsname
from table_people people left join
(
select
case when installation_date>delivery_date then act2.tool_id
else act1.tool_id end as recent_most_tool_id,
case when installation_date>delivery_date then act2.person_id
else act1.person_id end as recent_most_person_id
from table_activity1 act1 inner join table_activity2 act2
on act1.person_id=act2.person_id)X
on people.id=X.recent_most_person_id
inner join table_tools tools
on tools.id=X.recent_most_tool_id