Distinct columns after "ORDER BY" in SQL server 2014 - sql-server

I want to distinct columns after ORDER BY points.pPoint.
this is points table diagram:
I want something as following image on the right side but getting result as the left side:
and this is my code:
SELECT TOP(6) MedicalExpertise.meid
FROM physician INNER JOIN
MedicalExpertise ON physician.meid = MedicalExpertise.meid INNER JOIN
points ON physician.phId = points.phID
ORDER BY points.pPoint DESC

Perhaps something like this?
SELECT DISTINCT meid
FROM ( SELECT TOP ( 6 ) MedicalExpertise.meid
FROM physician
INNER JOIN MedicalExpertise ON physician.meid = MedicalExpertise.meid
INNER JOIN points ON physician.phId = points.phID
ORDER BY points.pPoint DESC ) d
ORDER BY 1 DESC;

Simply use distinct keyword,
Ex:
SELECT DISTINCT column1, column2, ...
FROM table_name;

Can you edit the original question what you really want? Does it have to be grouped by any column before getting distinct? Please update the question.

Related

How to left join onto existing query in SQL?

I am looking to left join another table because there are two columns in that table that I need to add to my query..how can I left join onto my existing query? For example the query I am using is similar to the one below..
select subject, sum(cnt_daily) as cnt,
min(cnt_daily) as min_cnt_daily, max(cnt_daily) as max_cnt_daily
from (
select study_date, subject, count(*) as cnt_daily
from mytable
where study_date >= '2022-01-01'
group by study_date, subject
) t
group by subject
I tried
select *
from mytable
left join table2
on mytable.id= table1.id
order by table1.id;
But i know this isnt right
You may use CTE:
WITH t AS (
select study_date, subject, count(*) as cnt_daily
from mytable
where study_date >= '2022-01-01'
group by study_date, subject
)
select subject, sum(cnt_daily) as cnt,
min(cnt_daily) as min_cnt_daily, max(cnt_daily) as max_cnt_daily
from t
group by subject
This could encourage reuse of the query inside CTE.

Using sub-queries and filter in WHERE clause while joining tables

SELECT DISTINCT(t1.Ticker),t2.SecurityID,t2.ClosePrice,t2.QuoteDateTime FROM [Hub].[SecurityMaster].[SecurityMasterDetails] as t1
INNER JOIN [Hub].[SecurityMaster].[SecurityPrices] as t2
ON t2.SecurityID =t1.SecurityID
WHERE t2.QuoteDateTime IN (SELECT max(QuoteDateTime) FROM [Hub].[SecurityMaster].[SecurityPrices]) AND t1.SecurityTypeName = 'REIT'
I get an output with no data. The subquery doesn't run along with the other filter in the WHERE clause. I am not sure what I am doing wrong. Can somebody please help!
If you are trying to get the lastest row from SecurityPrices for each Ticker, one option is to use cross apply():
select --distinct /* distinct not needed if `Ticker` is unique on `smd`
smd.Ticker
, sp.SecurityID
, sp.ClosePrice
, sp.QuoteDateTime
from [Hub].[SecurityMaster].[SecurityMasterDetails] as smd
cross apply (
select top 1
i.SecurityID
, i.ClosePrice
, i.QuoteDateTime
from [Hub].[SecurityMaster].[SecurityPrices] i
where i.SecurityID = smd.SecurityID
order by i.QuoteDateTime desc
) as sp
where SecurityTypeName = 'REIT' /* which table does this column belong to? */
I think your query would be
SELECT DISTINCT TOP 1 WITH TIES
t1.Ticker,
t2.SecurityID,
t2.ClosePrice,
t2.QuoteDateTime
FROM [Hub].[SecurityMaster].[SecurityMasterDetails] as t1
INNER JOIN [Hub].[SecurityMaster].[SecurityPrices] as t2 ON t2.SecurityID =t1.SecurityID
WHERE SecurityTypeName = 'REIT'
ORDER BY t2.QuoteDateTime DESC
You aren't getting results because the max(QuoteDateTime) record doesn't have SecurityTypeName = 'REIT'. I think you want the max(QuoteDateTime) for this SecurityTypeName, so this can be done with an INNER JOIN.
SELECT DISTINCT
(t1.Ticker),
t2.SecurityID,
t2.ClosePrice,
t2.QuoteDateTime
FROM [Hub].[SecurityMaster].[SecurityMasterDetails] as t1
INNER JOIN [Hub].[SecurityMaster].[SecurityPrices] as t2
ON t2.SecurityID =t1.SecurityID
INNER JOIN
(SELECT max(QuoteDateTime) DT FROM [Hub].[SecurityMaster].[SecurityPrices]) P on P.DT = t2.QuoteDateTime
WHERE SecurityTypeName = 'REIT'
EDIT
Your data doesn't have what you think it does, I suspect. Here is how you can check...
--Find the SecurityID that matches the max date
SELECT
SecurityID ,
max(QuoteDateTime) DT
FROM [Hub].[SecurityMaster].[SecurityPrices]
GROUP BY SecurityID
--I'm betting this ID isn't in your SecurityMasterDetails where the Type is REIT
SELECT DISTINCT
SecurityID
FROM SecurityMasterDetails
WHERE SecurityTypeName = 'REIT'
Since the SecurityID returned in the first query isn't in the second query result set, you are going to get NULL results.

How to concatenate 3 tables MSSQL Server

In a single database, I have three tables as below:
I want to concatenate them in some single table, any suggestion?
If I am understanding correctly your answer you want something like this:
CREATE TABLE COMBINED (/*Insert the set of fields here*/);
GO
INSERT INTO COMBINED
SELECT Table1.ProposalId
, /*all other Table1 fields*/
, Table2.ProposalId
/*all other Table2 fields*/
, Table3.ProposalId
, /*all other Table2 fields*/
FROM Table1
FULL JOIN Table2
ON Table1.ProposalId = Table2.ProposalId
FULL JOIN Table3
ON Table1.ProposalId = Table3.ProposalId;
This will match the rows with the same proposal id (but keep the all the its values as proposalid_1,proposalid_2... and for those that do not match will bring the full row and NULL for every other fields of the rest of the tables.
Thanks for your help the issue has been solved.
SELECT mtlreq.proposalid, mtlreq.prp_mtlreq_taskgrp,mtlreq.prp_mtlreq_taskcode,mtlreq.prp_mtlreq_itemcode,mtlreq.prp_mtlreq_rateper,mtlreq.prp_mtlreq_qty,mtlreq.prp_mtlreq_Inter_MaterCost,mtlreq.prp_mtlreq_UOM,mtlreq.item_short_desc, resreq.proposalid,resreq.prp_resreq_taskcode ,resreq.prp_resreq_resource,resreq.prp_resreq_usage,resreq.prp_resreq_uom,resreq.prp_resreq_rate,resreq.prp_resreq_overhd_pers
FROM (
SELECT proposalid,prp_mtlreq_taskgrp,prp_mtlreq_taskcode,prp_mtlreq_itemcode,prp_mtlreq_rateper,prp_mtlreq_qty,prp_mtlreq_Inter_MaterCost,prp_mtlreq_UOM,item_short_desc,
ROW_NUMBER() OVER (ORDER BY proposalid) AS rn
FROM prjdet_prp_taskwork_mtlreq ) AS mtlreq
FULL OUTER JOIN (
SELECT proposalid,prp_resreq_taskcode ,prp_resreq_resource,prp_resreq_usage,prp_resreq_uom,prp_resreq_rate,prp_resreq_overhd_pers,
ROW_NUMBER() OVER (ORDER BY proposalid) AS rn
FROM prjdet_prp_taskwork_resreq) AS resreq
ON mtlreq.rn = resreq.rn
FULL OUTER JOIN (
SELECT proposalid,mtprp_delv_lineno,mtprp_delv_itemcode,mtprp_delv_cost,mtprp_delv_linelevelmrg,mtprp_delv_proposedamt,
ROW_NUMBER() OVER (ORDER BY proposalid) AS rn
FROM prjproposal_delidtl ) AS delidtl
on mtlreq.rn = delidtl.rn and resreq.rn=delidtl.rn

Skip in SQL Server subquery

I want to use left outer join like this:
SELECT ...
FROM Table1
LEFT OUTER JOIN
(SELECT only e.g. 3rd record... , SomeField FROM Table2) tbl2
ON Table1.SomeField = tbl2.SomeField
How can I do that, if I need the subquery to select not just the 3rd record from Table2, but the 3rd record among the Table2 records that have SomeField = Table1.SomeField?
Thanks.
If this is sql server 2005 or newer, you might use row_number():
LEFT JOIN
(
select *
from
(
select *,
row_number() over (order by something) rn
from Table2
where Table2.Column = Table1.Column
) a
where a.rn = 3
) a
Unfortunately you need to nest it a level deeper because you cannot use row_number in a condition directly.
EDIT:
My bad - i didn't really notice the join part. If you want to join derived table, use this:
LEFT JOIN
(
select *,
row_number() over (partition by SomeField order by something) rn
from Table2
) tbl2
ON Table1.SomeField = tbl2.SomeField
AND tbl2.rn = 3
Note: you need ORDER BY in row_number() to keep things consistent.

Need help with the SQL Subquery

I want to count the total number of order detail rows over all orders a customer has ever had.
This is my query
SELECT SUM(
(SELECT count(*)
FROM dbo.Order_Details
WHERE dbo.Order_Details.OrderID = dbo.Orders.OrderID))
FROM dbo.Orders
WHERE dbo.Orders.CustomerID = "123"
SQL Server is giving me an error "Cannot perform an aggregate function on an expression containing an aggregate or a subquery."
Any help with this would be appreciated.
SELECT COUNT(*)
FROM Orders
INNER JOIN Order_Details ON Orders.OrderID = Order_Details.OrderID
WHERE Orders.CustomerID = "123"
Shouldn't it just be:
SELECT count(*) FROM dbo.Order_Details, dbo.Orders
WHERE dbo.Order_Details.OrderID = dbo.Orders.OrderID
AND dbo.Orders.CustomerID = "123"
You don't need the sum() since the count(*) is already going to give you the total.
SELECT (SELECT count(*)
FROM dbo.Order_Details
WHERE dbo.Order_Details.OrderID = dbo.Orders.OrderID)
FROM dbo.Orders
WHERE dbo.Orders.CustomerID = "123"
The Count(*) is doing the summation for you. Just remove the SUM aggregate from your expression.
I should think something like the following should do what you want:
select count(1) from dbo.order_details d
join dbo.orders o on d.OrderId=o.OrderId
where dbo.orders.CustomerID="123"
The following assumes you have a column in the Order_Details table called OrderDetailID. If not, just substitute for the unique identifier for the order detail record.
SELECT COUNT(DISTINCT OD.OrderDetailID)
FROM Orders O
LEFT JOIN Order_Details OD on (OD.OrderId = O.OrderId)
WHERE O.CustomerID = "123"

Resources