I have a table based on invoice items where I am trying to use SQL to detect at what dates the price or currency for the combination of material/customer has changed. The table contains invoices for several customers although the materials can be common.
My SQL skills are quite basic and I have tried several different approaches using GROUP BY and DISTINCT that I have found in other threads but I always seem to get stuck somewhere along the way.
This is basically what the data looks like:
Invoice Inv. Date Material Price Currency Per/Qty Customer
SE100 20140901 111111 1 EUR 1 840006
SE100 20140901 222222 2 EUR 1000 840006
SE100 20140901 333333 3 USD 1 840006
SE101 20140902 111111 1 EUR 1 840006
SE101 20140902 222222 2 EUR 1000 840006
SE101 20140902 333333 3 USD 1 840006
SE102 20140903 111111 2 EUR 1 840006
SE102 20140903 222222 2 USD 1000 840006
SE102 20140903 333333 3 USD 1 840006
SE103 20140904 111111 1 EUR 1 840006
SE103 20140904 222222 2 USD 1000 840006
SE103 20140904 333333 3 USD 1 840006
What I want to accomplish is basically to select the first row datewise for all distinct combinations of Customer/Material/Currency/Price and then subselect the entire rows (sorted by material) for those materials that occur more than once in the selection, thus indicating the price or currency has changed from the initial value.
The expected output from the query using the data in the table above would then look something like this:
Invoice Inv. Date Material Price Currency Per/Qty Customer
SE100 20140901 111111 1 EUR 1 840006
SE102 20140903 111111 2 EUR 1 840006
SE103 20140904 111111 1 EUR 1 840006
SE100 20140901 222222 2 EUR 1000 840006
SE102 20140903 222222 2 USD 1000 840006
I hope I managed to explain the problem in an understandable way. The database engine is SQL Server 2005 Express.
Any help would be appreciated...
The key word DISTINCT
in SQL has the meaning of "unique value". When applied to a column in a query it will return as many rows from the result set as there are unique, different values for that column. As a consequence it creates a grouped result set, and values of other columns are random unless defined by other functions (such as max, min, average, etc.)
If you meant to say you want to return all rows for which Col 06 has a specific value, then use the " where Col 06 = value
" clause
SELECT mt.*
FROM (
SELECT DISTINCT col6
FROM mytable
) mto
JOIN mytable mt
ON mt.id =
(
SELECT TOP 1 id
FROM mytable mti
WHERE mti.col6 = mto.col6
-- ORDER BY
-- id
-- Uncomment the lines above if the order matters
)
I think this is a direct translation of what you want:
select t.*
from mydata t join
(select Customer, Material, count(distinct price) as numprices
from mydata
group by Customer, Material
having count(distinct price) > 1
) cmcp
on t.customer = cmcp.customer and t.material = cmcp.material;
This leaves out the currency. Unfortunately, SQL Server doesn't support multiple arguments to distinct
. You can include it this way:
select t.*
from mydata t join
(select Customer, Material,
count(distinct cast(price as varchar(255)) + ':' + currency) as numprices
from mydata
group by Customer, Material
having count(distinct cast(price as varchar(255)) + ':' + currency) > 1
) cmcp
on t.customer = cmcp.customer and t.material = cmcp.material;
Most databases support window/analytic functions, so you can also phrase this as:
select t.*
from (select t.*,
min(cast(price as varchar(255)) + ':' + currency)) over (partition by Customer, Material) as minprice,
max(cast(price as varchar(255)) + ':' + currency)) over (partition by Customer, Material) as maxprice
from mydata t
) t
where minprice <> maxprice
order by Material, Inv_Date;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.