I am trying to get a total hours from a dataset and because you can have the same asset with the same company (company_B) twice at two different times I have this join issue. I know I want the min for company_B gone and the Max for company_B gone because they represent wrong dates being matched. The negative is easy but what about the Max?
I have:
AssetID------StartDate-------FinishDate-------CompanyName----HoursOnSite
22222-------2016-02-12-------2016-02-20-------Company_A--------192
22222-------2016-02-01-------2016-02-09-------Company_B--------208 (keep)
22222-------2016-02-12-------2016-02-09-------Company_B-------(-56) (remove)
22222-------2016-02-01-------2016-02-21-------Company_B--------480 (remove)
22222-------2016-02-12-------2016-02-21-------Company_B--------216 (keep)
55555-------2016-02-18-------2016-02-22-------Company_C--------96
99584-------2016-02-22-------2016-02-25-------Company_D--------63
I think you can do the query for the records with max and min HoursOnSite for company B, and use (not in) or not equal to exclude those records.
If you still have concern, please paste your query.
I'm assuming that there has to be atleast 3 instances of unique assetid - companyname combination for the Max, Min filters to work. You can change it in the final where statement tO suit your requirement
WITH CTE
AS (
SELECT *
,count(CompanyName) OVER (PARTITION BY AssetID,CompanyName) AS a
FROM <TABLE_NAME>
)
SELECT *
FROM CTE
WHERE HoursOnSite NOT IN (
SELECT MAX(HoursOnSite)
FROM <TABLE_NAME>
)
AND gdp NOT IN (
SELECT min(HoursOnSite)
FROM <TABLE_NAME>
)
AND a > 2 --MODIFY AS PER YOUR REQUIREMENT
Related
I have a table like following :
Orderserialno SKU Units
1234-6789 2x3 5
1234-6789 4x5 7
1334-8905 4x5 2
1334-8905 6x10 2
I need to get the count of distinct orderserialno where Units are not equal within a orderserialno. There could be more combinations of Sku's in an order than what I have mentioned but the eventual goal is to get those orders where units corresponding to various SKUs (in that order) are not equal.
In the above case I should get answer as 1 as orderserialno 1234-6789 has different units.
Thanks
This is a relatively simple GROUP BY query:
SELECT Orderserialno, Units
FROM MyTable
GROUP BY Orderserialno, Units
HAVING COUNT(1) > 1
This would give you all pairs (Orderserialno, Units). To project out the Units, nest this query inside a DISTINCT, like this:
SELECT DICTINCT(Orderserialno) FROM (
SELECT Orderserialno, Units
FROM MyTable
GROUP BY Orderserialno, Units
HAVING COUNT(1) > 1
)
If you need only the total count of Orderserialnos with multiple units, replace DICTINCT(Orderserialno) with COUNT(DICTINCT Orderserialno).
To get the list of such order numbers, use an aggregation query:
select OrderSerialNo
from t
group by OrderSerialNo
having min(Units) <> max(Units)
This uses a trick to see if the units value changes. You can use count(distinct), but that usually incurs a performance overhead. Instead, just compare the minimum and maximum values. If they are different, then the value is not constant.
To get the count, use this as a subquery:
select count(*)
from (select OrderSerialNo
from t
group by OrderSerialNo
having min(Units) <> max(Units)
) t
I am trying to find a division with the lowest population density to do so i did the following:
SELECT P.edname, MIN((P.total_area*1000)/P.total2011) AS "Lowest population density"
FROM eds_census2011 P
GROUP BY P.edname
HAVING COUNT (*)> 1
total_area is multiplied by 1000 (so it is in square metres) and divide by total population.
I want only one record displaying the division (edname) and the population density wich is calculated (MIN((P.total_area*1000)/P.total2011)), instead I get all the records - not even sorted...
The problem is that I have to group it by edname, if I leave out the GROUP BY and HAVING lines I get an error. Any help is greatly appriciated!
Try
SELECT edname, (total_area*1000/total2011) density
FROM eds_census2011
WHERE (total_area*1000/total2011) = (SELECT MIN(total_area*1000/total2011) FROM eds_census2011)
SQLFiddle
A 'Return only one row' rule could be easily enforced by using LIMIT 1 if it's really necessary
Without subquery:
SELECT p.edname, min((p.total_area * 1000)/p.total2011) AS lowest_pop
FROM eds_census2011 p
GROUP BY p.edname
HAVING COUNT (*) > 1
ORDER BY 2
LIMIT 1;
This one returns only 1 row (if any qualify), even if multiple rows have equally low density.
If you just want the lowest density, period, this can be much simpler:
SELECT edname, (total_area * 1000)/total2011) AS lowest_pop
FROM eds_census2011
ORDER BY 2
LIMIT 1;
I have two subquerys both calculating sums. I would like to do an Artithmetic Minus(-) with the result of both Querys . eg Query1: 400 Query2: 300 Result should be 100.
Obvious a basic - in the query does not work. The minus works as MINUS on sets. How can I solve this? Do you have any ideas?
SELECT CustumersNo FROM Custumers WHERE
(
SELECT SUM(value) FROM roe WHERE roe.credit = Custumers.CustumersNo
-
SELECT SUM(value) FROM roe WHERE roe.debit = Custumers.CustumersNo
)
> 500
Using Informix - sorry missed that point
To get the original syntax to work, you would need to surround the sub-selects in parentheses:
SELECT CustumersNo
FROM Custumers
WHERE ((SELECT SUM(value) FROM roe WHERE roe.credit = Custumers.CustumersNo)
-
(SELECT SUM(value) FROM roe WHERE roe.debit = Custumers.CustumersNo)
) > 500
Note that aggregates are defined to ignore nulls in the values they aggregate in standard SQL. However, the SUM of an empty set of rows is NULL, not zero.
You can get inventive and devise ways to always have a value for each customer listed in the roe table, such as:
SELECT CustomersNo
FROM (SELECT CustomersNo, SUM(value) AS net_credit
FROM (SELECT credit AS CustomersNo, +value
UNION
SELECT debit AS CustomersNo, -value
) AS x
GROUP BY CustomersNo
) AS y
WHERE net_credit > 500;
You can also do that with an appropriate HAVING clause if you wish. Note that this avoids issues with customers who have credit entries but no debit entries or vice versa; all the entries that are present are treated appropriately.
Your misspelling (or unorthodox spelling) of 'customers' is nearly as good as 'costumers'.
Something like what you tried should work. It may be a syntax problem, and it may depend on what type of SQL you are using. However, an approach like this would be more efficient:
Update: I see you were having a problem with nulls, so I updated it to handle nulls properly.
select CustumersNo from (
select CustumersNo,
sum(coalesce(roecredit.value,0)) - sum(coalesce(roedebit.value,0))
as balance
FROM Custumers
join roe roecredit on roe.credit = Custumers.CustumersNo
join roe roedebit on roe.debit = Custumers.CustumersNo
group by CustumersNo
)
where balance > 500
Caveat: I don't have experience with Informix specifically.
I have a database table that Stores Maximum and Minimum Price Breaks for a Product.
Does anyone know of the SQL which say if I have a break from one Max to the Min of the next item. E.g. 1-10 12-20 I would like it to return me either the numbers that are missing or at the very least a count or bool if it can detect a break from the Absolute Min and the Absolute Max by going through each range.
SQL Server (MSSQL) 2008
For a database that supports window functions, like Oracle:
SELECT t.*
, CASE LAG(maxq+1, 1, minq) OVER (PARTITION BY prod ORDER BY minq)
WHEN minq
THEN 0
ELSE 1
END AS is_gap
FROM tbl t
;
This will produce is_gap = 1 for a row that forms a gap with the previous row (ordered by minq). If your quantity ranges can overlap, the required logic would need to be provided.
http://sqlfiddle.com/#!4/f609e/4
Something like this, giving max quantities that aren't the overall max for the product and don't have a min quantity following them:
select prev.tbProduct_Id,prev.MaxQuantity
from yourtable prev
left join (select tbProduct_ID, max(MaxQuantity) MaxQuantity from yourtable group by tbProduct_id) maxes
on maxes.tbProduct_ID=prev.tbProduct_Id and maxes.MaxQuantity=prev.MaxQuantity
left join yourtable next
on next.tbProduct_Id=prev.tbProduct_Id and next.MinQuantity=prev.MaxQuantity+1
where maxes.tbProduct_Id is null and next.tbProduct_Id is null;
This would fail on your sample data, though, because it would expect a row with MinQuantity 21, not 20.
I tried this query on MySQL server (5.1.41)...
SELECT max(volume), dateofclose, symbol, volume, close, market FROM daily group by market
I got this result:
max(volume) dateofclose symbol volume close market
287031500 2010-07-20 AA.P 500 66.41 AMEX
242233000 2010-07-20 AACC 16200 3.98 NASDAQ
1073538000 2010-07-20 A 4361000 27.52 NYSE
2147483647 2010-07-20 AAAE.OB 400 0.01 OTCBB
437462400 2010-07-20 AAB.TO 31400 0.37 TSX
61106320 2010-07-20 AA.V 0 0.24 TSXV
As you can see, the maximum volume is VERY different from the 'real' value of the volume column?!?
The volume column is define as int(11) and I got 2 million rows in this table but it's very far from the max of MyISAM storage so I cannot believed this is the problem!? What is also strange is data get show from the same date (dateofclose). If I force a specific date with a WHERE clause, the same symbol came out with different max(volume) result. This is pretty weird...
Need some help here!
UPDATE :
Here's my edited "working" request:
SELECT a.* FROM daily a
INNER JOIN (
SELECT market, MAX(volume) AS max_volume
FROM daily
WHERE dateofclose = '20101108'
GROUP BY market
) b ON
a.market = b.market AND
a.volume = b.max_volume
So this give me, by market, the highest volume's stock (for nov 8, 2010).
As you can see, the maximum volume is VERY different from the 'real' value of the volume column?!?
This is because MySQL rather bizarrely doesn't GROUP things in a sensical way.
Selecting MAX(column) will get you the maximum value for that column, but selecting other columns (or column itself) will not necessarily select the entire row that the found MAX() value is in. You essentially get an arbitrary (and usually useless) row back.
Here's a thread with some workarounds using subqueries:
How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
This is a subset of the "greatest n per group" problem. (There is a tag with that name but I am a new user so I can't retag).
This is usually best handled with an analytic function, but can also be written with a join to a sub-query using the same table. In the sub-query you identify the max value, then join to the original table on the keys to find the row that matches the max.
Assuming that {dateofclose, symbol, market} is the grain at which you want the maximum volume, try:
select
a.*, b.max_volume
from daily a
join
(
select
dateofclose, symbol, market, max(volume) as max_volume
from daily
group by
dateofclose, symbol, market
) b
on
a.dateofclose = b.dateofclose
and a.symbol = b.symbol
and a.market = b.market
Also see this post for reference.
Did you try adjusting your query to include Symbol in the grouping?
SELECT max(volume), dateofclose, symbol,
volume, close, market FROM daily group by market, symbol