First time posting here, hopes it goes well.
I try to make a query with Oracle SQL Developer, where it returns a customer_ID from a table and the time of the payment from another. I'm pretty sure that the problems lies within my logicflow (It was a long time I used SQL, and it was back in school so I'm a bit rusty in it). I wanted to list the IDs as DISTINCT and ORDER BY the dates ASCENDING, so only the first date would show up.
However the returned table contains the same ID's twice or even more in some cases. I even found the same ID and same DATE a few times while I was scrolling through it.
If you would like to know more please ask!
SELECT DISTINCT
FIRM.customer.CUSTOMER_ID,
FIRM.account_recharge.X__INSDATE FELTOLTES
FROM
FIRM.customer
INNER JOIN FIRM.account
ON FIRM.customer.CUSTOMER_ID = FIRM.account.CUSTOMER
INNER JOIN FIRM.account_recharge
ON FIRM.account.ACCOUNT_ID = FIRM.account_recharge.ACCOUNT
WHERE
FIRM.account_recharge.X__INSDATE BETWEEN TO_DATE('14-01-01', 'YY-MM-DD') AND TO_DATE('14-12-31', 'YY-MM-DD')
ORDER
BY FELTOLTES
Your select works like this because a CUSTOMER_ID indeed has more than one X__INSDATE, therefore the records in the result will be distinct. If you need only the first date then don't use DISTINCT and ORDER BY but try to select for MIN(X__INSDATE) and use GROUP BY CUSTOMER_ID.
SELECT DISTINCT FIRM.customer.CUSTOMER_ID,
FIRM.account_recharge.X__INSDATE FELTOLTES
Distinct is applied to both the columns together, which means you will get a distinct ROW for the set of values from the two columns. So, basically the distinct refers to all the columns in the select list.
It is equivalent to a select without distinct but a group by clause.
It means,
select distinct a, b....
is equivalent to,
select a, b...group by a, b
If you want the desired output, then CONCATENATE the columns. The distict will then work on the single concatenated resultset.
Related
I have read many answers here, but until now nothing could help me. I'm developing a ticket system, where each ticket has many updates.
I have about 2 tables: tb_ticket and tb_updates.
I created a SELECT with subqueries, where it took a long time (about 25 seconds) to get about 1000 rows. Now I changed it to INNER JOIN instead many SELECTs in subqueries, it is really fast (70 ms), but now I get duplicates tickets. I would like to know how can I do to get only the last row (ordering by time).
My current result is:
...
67355;69759;"COMPANY X";"2014-08-22 09:40:21";"OPEN";"John";1
67355;69771;"COMPANY X";"2014-08-26 10:40:21";"UPDATE";"John";1
The first column is the ticket ID, the second is the update ID... I would like to get only a row per ticket ID, but DISTINCT does not work in this case. Which row should be? Always the latest one, so in this case 2014-08-26 10:40:21.
UPDATE:
It is a postgresql database. I did not share my current query because it has only portuguese names, so I think it would not help at all.
SOLUTION:
Used_By_Already had the best solution to my problem.
Without the details of your tables one has to guess the field names, but it seems that tb_updates has many records for a single record in tb_ticket (a many to one relationship).
A generic solution to your problem - to get just the "latest" record - is to use a subquery on tb_updates (see alias mx below) and then join that back to tb_updates so that only the record that has the latest date is chosen.
SELECT
t.*
, u.*
FROM tb_ticket t
INNER JOIN tb_updates u
ON t.ticket_id = u.ticket_id
INNER JOIN (
SELECT
ticket_id
, MAX(updated_at) max_updated
FROM tb_updates
GROUP BY
ticket_id
) mx
ON u.ticket_id = mx.ticket_id
AND u.updated_at = mx.max_updated
;
If you have a dbms that supports ROW_NUMBER() then using that function can be a very effective alternative method, but you haven't informed us which dbms you are using.
by the way:
These rows ARE distinct:
67355;69759;"COMPANY X";"2014-08-22 09:40:21";"OPEN";"John";1
67355;69771;"COMPANY X";"2014-08-26 10:40:21";"UPDATE";"John";1
69759 is different to 69771, and that is enough for the 2 rows to be DISTINCT
there are difference in the 2 dates also.
distinct is a row operator which means is considers the entire row, not just the first column, when deciding which rows are unique.
Used_By_Already's solution would work just fine. I'm not sure on the performance but another solution would be to use cross apply, though that is limited to only a few DBMS's.
SELECT *
FROM tb_ticket ticket
CROSS APPLY (
SELECT top(1) *
FROM tb_updates details
ORDER BY updateTime desc
WHERE details.ticketID = ticket.ticketID
) updates
U Can try something like below if your updateid is identity column:
Select ticketed, max(updateid) from table
group by ticketed
To obtain last row you have to end your query with order by time desc then use TOP (1) in the select statement to select only the first row in the query result
ex:
select TOP (1) .....
from .....
where .....
order by time desc
I want to get unique value form table. But all values should be unique.
So suggest how to get.
SELECT DISTINCT ProCode
, id,SubCat
,SmlImgPath
,RupPrice
,ActualPrice
,ProName
FROM product
WHERE ProCode='FZ10003-EBA';
(one day I may be able to post comments!)
SQLFiddle to show normal, distinct and returning a single row
SELECT DISTINCT works fine but it doesn't work the way you want it to work. From the data you posted in the comment under Klas' answer, it's clear you're expecting a single result when there are data differences somewhere in the columns. For example
/Products/CELEBRITY/KANGANA
is completely DISTINCT from
/Products/SALWAR
What you appear to be looking for cannot work with DISTINCT nor can it work with GROUP BY. Basically the only way two (or three, or ten, or 100) rows will become ONE row is if the data in ALL SEVEN COLUMNS in your SELECT are IDENTICAL.
Take a step back and think about what it is, exactly, you're trying to achieve here.
Are you saying that you want one record only? This is called aggregation. In case there are more records then one (three in your example), you would have to decide for each column, which value to show.
Which SubCat, which SmlImgPath, etc. do you want to see in your result line? The maximum value? The minimum? Or the string 'various'? An example:
SELECT
ProCode
, CASE WHEN MIN(id) <> MAX(id) THEN 'various' ELSE MIN(id) END
, MIN(SubCat)
, MAX(SmlImgPath)
, AVG(RupPrice)
, AVG(ActualPrice)
, MAX(ProName)
FROM product
WHERE ProCode='FZ10003-EBA'
GROUP BY ProCode;
DISTINCT refers to all selected columns, so the answer is that your SELECT already does that.
EDIT:
It seems your problem isn't related to DISTINCT. What you want is to get a single row when your search returns multiple rows.
If you don't care which row you get then you can use:
MS SQL Server syntax:
SELECT TOP 1 ProCode
, id,SubCat
,SmlImgPath
,RupPrice
,ActualPrice
,ProName
FROM product
WHERE ProCode='FZ10003-EBA';
MYSQL syntax:
SELECT ProCode
, id,SubCat
,SmlImgPath
,RupPrice
,ActualPrice
,ProName
FROM product
WHERE ProCode='FZ10003-EBA'
LIMIT 1;
Oracle syntax:
SELECT ProCode
, id,SubCat
,SmlImgPath
,RupPrice
,ActualPrice
,ProName
FROM product
WHERE ProCode='FZ10003-EBA'
AND rownum <= 1;
I am trying to create database query, which will select rows from one table, create periods from those rows (using Lag window function), and join the query with rows from different table, where it sums value(s)from one column per row in first table.
Table A:
id,
created_at,
object_id
Table B:
id,
end_time,
value,
object_id
And rows, that query yields should consist of columns something like:
lag(tablea.created_at) over(tablea.object_id, tablea.created_at),
tablea.created_at,
tablea.object_id
sum(tableb.value) where it sums the tableb.value from matching period
I tried creating query where i put the window function into WHERE clause only to get an error. I also tried puting the period into join on clause but that also raised an error.
It is no problem, if it is not possible. I just want to know if it possible and in that case how it is possible. If it is not possible, then i just will try to come up with alternative aproach.
Edit: link to example sqlfiddle: http://sqlfiddle.com/#!1/c7878
Edit2: The SQL i tried was something like:
SELECT lag(a.created_at, a.created_at, a.object_id, sum(b.value) from tablea a left join tableb b on (something) order by a.object_id, a.created_at
But obviously that did not work, because i could not use window function in ON clause. That's where i got stuck
I know this has to be an easy select but I am having no luck figuring it out. I've got a table has a field of customer grouping codes and I'm trying to get a count of each distinct character 2 through 6 sets. In my past foxpro experience a simple
select distinct substr(custcode,2,5), count (*) from a group by 1
would work, but this doesn't appear to work in sql server queries. The error message indicated it didn't like using the number reference in the group by so I changed it to custcode but the count just returns 1 for each, as I assume the count is after the distinct occurs so there is only one. If I change the count to count(distinct substring(custcode,2,5)) and remove the first distinct substring I just get a count of how many different codes exist. Can someone point out what I'm doing wrong here? Thanks.
The DISTINCT and GROUP BY are redundant, you just want GROUP BY, and you want to GROUP BY the same thing you are selecting:
select substr(custcode,2,5), count (*)
from a
group by substr(custcode,2,5)
In SQL Server you can use column aliases/numbers in the ORDER BY clause, but not in GROUP BY.
Ie. ORDER BY 1 will order by the first selected column, but many consider it bad practice to use column indexes, using aliases/column names is clearer.
I'm having a little problem with one query that I'm writing. I've a lot of joins, and a lot of columns that I extract, in the where clause I compare date column with the minimum value of the same table. But when I got a same date for two rows, I need to get only one row. The where clause is like that:
bt.da2 = (select min(btreg.da2) from bt btreg.....
the query results a lot of customers, every customer has that bt.da2 date. I need when one customer has two rows, with the same value of the bt.da2 , I need to take only one of the two rows, not the two.
I may not explained myself clear. Please if anyone have a little clue what I'm asking, and something is not clear, please ask me.
I'm using PostgreSQL 8.3
Regards,
Julian
It's hard to tell with so little information, but I would try something like this:
select *
from (
select product_id, -- assumed to be the primary key
...
row_number() over (partition by product_id order by bt.da2) as rn
from products pr
left join bt on bt.da2 = pr.some_col
) t
where rn = 1
the row_number() function is used to create consecutive numbers for each product. The outer where clause then picks the first one. You can change the order by in the window definition to influence which one you pick.
You should be able to sort out duplicate values of da2 using:
bt.da2 = (select distinct min(btreg.da2) from bt btreg.....
I tried this out using PostgreSQL 9.1, but I am sure the distinct keyword will work as expected in 8.4 as well.