DISTINCT statement in SQL 2008 - sql-server-2008

How do you get DISTINCT to end only at 'serviceType'? I've tried union and intersect to no avail.
$tsql = "SELECT DISTINCT serviceType, product, provider, rate, qty, updated FROM contracts WHERE client='{$_POST['client']}' ";
I need to see the latest updated serviceType record with the rest of the available information, but not every little change that I make. However, I would like to keep the changes as an archive.

This is how I would write that query in SQL Server:
SELECT distinct main.serviceType, b.product, b.provider, b.rate, b.qty, b.updated
FROM contracts as main
Outer Apply (Select Top 1
serviceType, product, provider, rate, qty, updated
FROM contracts as sub
where main.serviceType = sub.serviceType
Order by updated desc
) b
WHERE client= #client

Ok I got it:
$tsql = "SELECT distinct main.serviceType, b.product, b.provider, b.rate, b.qty, b.updated
FROM contracts AS main
OUTER APPLY (SELECT TOP 1
serviceType, product, provider, rate, qty, updated
FROM contracts as sub
WHERE main.serviceType = sub.serviceType AND client='{$_POST['client']}'
ORDER BY ID DESC
) b
WHERE client='{$_POST['client']}' ";
Thanks Feryal. I just had to change the ORDER BY to ID since I made numerous changes during the same day.

Related

Display zero in group by sql for a particular period

I am trying to run the following query to obtain the sales for each type of job for a particular period. However for certain months where there are no jobs of a particular job type performed no 0 is displayed in sales.
How can i display the zeros in such a condition.
Here is the sql query-
select Year(postedOn), month(postedOn), jobType, sum(price)
from tbl_jobs
group by jobType, year(postedOn), month(postedOn)
order by jobType, year(postedOn), month(postedOn)
Typically, this is where your all-purpose calendar or numbers table comes in to anchor the query with a consistent sequential set:
SELECT job_summary.*
FROM Calendar
CROSS JOIN (
-- you may not have though about this part of the problem, though
-- what about years/months with missing job types?
SELECT distinct jobType FROM tbl_jobs
) AS job_types
LEFT JOIN (
select Year(postedOn) AS year,month(postedOn) as month,jobType ,sum(price)
from tbl_jobs
group by jobType, year(postedOn), month(postedOn)
) job_summary
ON job_summary.jobType = job_types.jobType
AND job_summary.year = Calendar.year
AND job_summary.month = Calendar.month
WHERE Calendar.day = 1 -- Assuming your calendar is every day
AND calendar.date BETWEEN some_range_goes_here -- you don't want all time, right?
order by job_types.jobType, Calendar.year, Calendar.month

SELECT only first and last results

A client can have more than one equipment (SerialNo). Each equipment has a cost and every month there is data recorded for each equipment. I'm trying to select only the first and last result for each equipment based on the queried period.
"
SELECT i.SerialNo
, p.Name
, c.Cost
, ci.DataDate
, ci.Data
,
FROM install i
JOIN product p USING (ProductId)
JOIN counter c USING (InstallId)
JOIN counter_item ci USING (CounterId)
WHERE i.ClientId LIKE $clientId
AND MONTH(ci.DataDate) BETWEEN $mStart AND $mEnd
";
This select works but it retrieves all records between the starting date and finishing date.
I tried, to get the top results and figured I would use A UNION ALL to combine with the bottom results (ci.DataDate ASC), but it's not working. I only get the first record encounter.
GROUP BY i.SerialNo
ORDER BY ci.DataDate DESC
It's like ORDER BY has no effect at all.
In counter_item you find the first and last DataDate per CounterId for the time range. So find these first by aggregation and use this information in order to join the desired records:
SELECT i.SerialNo,
p.Name,
c.Cost,
ci.DataDate,
ci.Data
FROM install i
JOIN product p ON p.ProductId = i.ProductId
JOIN counter c ON c.InstallId = i.InstallId
JOIN
(
SELECT CounterId, MIN(DataDate) AS MinDate, MAX(DataDate) AS MaxDate
FROM counter_item
WHERE MONTH(DataDate) BETWEEN $mStart AND $mEnd
GROUP BY CounterId
) minmax ON minmax.CounterId = c.CounterId
JOIN counter_item ci ON ci.CounterId = minmax.CounterId
AND ci.DataDate IN (minmax.MinDate, minmax.MaxDate)
WHERE i.ClientId LIKE $clientId
ORDER BY i.SerialNo, ci.DataDate
You could do it in next way, here is just general idea of how that could be done:
select * from table
where
([row] = (select max([row]) from table ) or
[Date] = (select min([row]) from table ))
You may also be able to use a cross apply. Something like this, untested rough sample:
SELECT i.SerialNo,
p.Name,
c.Cost,
MIN(ci.DataDate) as MinDate,
b.MaxDate,
ci.Data,
FROM install i
CROSS APPLY (SELECT
MAX(ci.DataDate) as MaxDate
FROM install
JOIN counter_item ci USING (CounterId)
WHERE i.ClientId LIKE $clientId
AND MONTH(ci.DataDate) BETWEEN $mStart AND $mEnd) b
WHERE i.ClientId LIKE $clientId
AND MONTH(ci.DataDate) BETWEEN $mStart AND $mEnd
GROUP BY i.SerialNo
ORDER BY ci.DataDate DESC

SQL sort data based on different columns

I need some help with an SQL problem. I'm not sure it's possible to do, but i have this table:
Obtained from this SQL statement:
SELECT distinct Account.Box, Account.Name, Account.Currency, Account.LastUpdated, Account.LastUpdatedBy, Transactions.Totals
FROM Account
LEFT JOIN Transactions
ON Account.AccountGUID = Transactions.AccountGUID
What i would like to end up with is this result:
So basically comparing the Totals for each groups of Name or Currency, to obtain the highest Totals for each group. (NULL values are to be replaced by zeroes).
You seem to just want a group by:
SELECT a.Box, a.Name, a.Currency, a.LastUpdated, a.LastUpdatedBy,
MAX(t.Totals) as Totals
FROM Account a LEFT JOIN
Transactions t
ON a.AccountGUID = t.AccountGUID
GROUP BY a.Box, a.Name, a.Currency, a.LastUpdated, a.LastUpdatedBy;
Note: I also added table aliases to make the query easier to understand.
Try with this following one ,hope you will get the result what you are expecting.
select * from
(SELECT distinct Account.Box, Account.Name, Account.Currency, Account.LastUpdated, Account.LastUpdatedBy, Transactions.Totals as Totals
FROM Account
LEFT JOIN Transactions
ON Account.AccountGUID = Transactions.AccountGUID) as p
where p.Totals = (select max(totals) from transactions)
group by Box, Name, Currency, LastUpdated, LastUpdatedBy ;
(or)
use the following one also
SELECT a.Box, a.Name, a.Currency, a.LastUpdated, a.LastUpdatedBy,
MAX(t.Totals) as Totals
FROM Account a LEFT JOIN
Transactions t
ON a.AccountGUID = t.AccountGUID
GROUP BY a.Box, a.Name, a.Currency, a.LastUpdated, a.LastUpdatedBy;
Thanks.

SQL Query - Determine who has only one gift record

I would like to know how I can write a SQL Script so a within a group of individuals initially selected:
SELECT [RECORDS].[CONSTITUENT_ID]
,[RECORDS].[FIRST_NAME]
,[RECORDS].[LAST_NAME]
,[DATEADDED]
,[DTE]
,[Amount]
,[REF]
,[TYPE]
FROM [re7].[dbo].[GIFT]
INNER JOIN [re7].[dbo].[RECORDS]
ON GIFT.CONSTIT_ID LIKE RECORDS.ID
WHERE ([DTE] BETWEEN '2/7/2015' AND '2/8/2015')
ORDER BY [DATEADDED] DESC
select only individuals who are "First Time Donors" (or someone who only has one gift in [re7].[dbo].[GIFT].
[RECORDS] is a table of all the constituents.
[GIFT] is a table of all recorded Gifts.
The output of the above Query, is just a table with:
CONSTITUENT_ID, FIRST_NAME, LAST_NAME, DATEADDED, DTE, Amount, REF, TYPE
I pretty much want to see the same output format, but I would like the query to select only CONSTITUENT_ID who only have 1 GIFT (by their Record ID) in [re7].[dbo].[GIFT].
I apologize for the lack of data to show. I wish I could describe better....
SELECT [RECORDS].[CONSTITUENT_ID]
,[RECORDS].[FIRST_NAME]
,[RECORDS].[LAST_NAME]
,[DATEADDED]
,[DTE]
,[Amount]
,[REF]
,[TYPE]
FROM [re7].[dbo].[GIFT]
INNER JOIN [re7].[dbo].[RECORDS]
ON GIFT.CONSTIT_ID LIKE RECORDS.ID
WHERE ([DTE] BETWEEN '2/7/2015' AND '2/8/2015')
AND GIFT.CONSTIT_ID IN (
SELECT CONSTIT_ID FROM re7.dbo.Gift GROUP BY CONSTIT_ID HAVING COUNT(*) = 1
) /* another option is to add a subquery to the query you already had */
ORDER BY [DATEADDED] DESC
This solution simply selects all the constituents who have made only one donation and then joins to that, thereby limiting the result set.
SELECT
r.[CONSTITUENT_ID]
,r.[FIRST_NAME]
,r.[LAST_NAME]
,[DATEADDED]
,[DTE]
,[Amount]
,[REF]
,[TYPE]
FROM
(select [CONSTIT_ID] from [re7].[dbo].[GIFT] group by [CONSTIT_ID] having count([CONSTIT_ID]) = 1) g1
inner join [re7].[dbo].[GIFT] g
on g.[CONSTIT_ID] = g1.[CONSTIT_ID]
INNER JOIN [re7].[dbo].[RECORDS] r
ON g.CONSTIT_ID LIKE r.RECORDS.ID
WHERE ([DTE] BETWEEN '2/7/2015' AND '2/8/2015')
ORDER BY [DATEADDED] DESC

MySQL MAX(datetime) not working

I am trying to retrieve the max(date_entered) for a group of computer_ids.
The first query won't return accurate results. The second query gives me accurate results but essentially hangs unless I filter by a specific computer_id.
I'd rather use this first query
SELECT *, max(reports.date_entered)
FROM reports, hardware_reports
WHERE reports.report_id=hardware_reports.report_id
GROUP BY computer_id;
than this second query
SELECT *
FROM reports a
JOIN hardware_reports
ON a.report_id=hardware_reports.report_id
AND a.date_entered = (
SELECT MAX(date_entered)
FROM reports AS b
WHERE a.computer_id = b.computer_id)
and computer_id = 1648;
I need to either optimize second or get max to work in first.
You can alternative join it on a subquery that gets the latest record for every computer_ID.
SELECT a.*, c.*
FROM reports a
INNER JOIN
(
SELECT computer_ID, MAX(date_entered) date_entered
FROM reports
GROUP BY computer_ID
) b ON a.computer_ID = b.computer_ID
AND a.date_entered = b.date_entered
INNER JOIN hardware_reports c
ON a.report_id = c.report_id
To make it more efficient, provide an index on columns:
ALTER TABLE reports INDEX idx_report_compDate (computer_ID, date_entered)