The MIN() Function Ms Access - sql

this is a sample sql query that i created ms access query. i am trying to get only one row the min(DATE). how ever when i run my query i get multiple lines. any hits? thanks
SELECT tblWarehouseItem.whiItemName,
tblWarehouseItem.whiQty,
tblWarehouseItem.whiPrice,
Min(tblWarehouseItem.whiDateIn) AS MinOfwhiDateIn,
tblWarehouseItem.whiExpiryDate,
tblWarehouseItem.whiwrhID
FROM tblWarehouseItem
GROUP BY tblWarehouseItem.whiDateIn,
tblWarehouseItem.whiItemName,
tblWarehouseItem.whiQty,
tblWarehouseItem.whiPrice,
tblWarehouseItem.whiExpiryDate,
tblWarehouseItem.whiwrhID;
If i have my sql code like that is working as it should:
SELECT MIN(tblWarehouseItem.whiDateIn) FROM tblWarehouseItem;

In the first query, you group by a number of columns. That means the minimum value will be calculated for each group, which in turn means you may have multiple rows. On the other hand, the second query will only get the minimum value for the specified column from all rows, so that there is only one row in the result set.
A simple example is shown below to illustrate the above.
Table:
Key Value
1 1
1 2
2 3
2 4
On Group By Key:
GroupKey MinValue
1 = min(1,2) = 1 -> Row 1
2 = min(3,4) = 3 -> Row 2
On Min (Value)
MinValue
=min(1,2,3,4) = 1 -> Row 1
For a table like above, if you want to select all rows and also show the minimum value from whole table rather than per group, you can do something like this:
select key, (select min(value) from table)
from table

SELECT WI.*
FROM tblWarehouseItem AS WI INNER JOIN (SELECT whiimtID, MIN(tblWarehouseItem.whiDateIn) AS whiDateIn
FROM tblWarehouseItem
GROUP BY whiimtID) AS MinWI ON (WI.whiDateIn = MinWI.whiDateIn) AND (WI.whiimtID = MinWI.whiimtID);

Related

Filter with SQL Server by Group ID

I have two tables and I need to filter the data by filter id depends on the relation to to filter group id.
For example I have this two tables:
Table 1:
ItemID
FilterID
3
122
3
123
3
4
17
123
Table 2:
FilterID
FilterGroupID
122
5
123
5
4
1
If I search by filter id = 123 than all item id with this filter need to be returned.
If I search two or more different filter id that have different group id I need to get only the item ids that have all filter id and group id.
Desired output:
first input: 123 -> return item id =3 and item id = 17
second input: 123,4 -> return item id = 3 because filter id 123 belong to group id 5 and filter id 4 belong to group id 1 and item id 3 is the only one that has this two filters.
third input: 122,123 -> return item id =3 and item id = 17 because both filter id belong to same group.
I am getting a little lost with this query and I will be glad to get some help.
I’ll try to simplify it: Let’s say we have group filter of size and group filter of color. If I filter by size S or M than I need to get all items with this sizes. If I want to add color like blue than the answer will cut the result by: item with size S or M and Color blue. So filter from different group may cut some results
It seems that you want to get every ItemID which has at least one matching filter from each FilterGroupID within your filter input. So within each group you have or logic, and between groups you have and logic
If you store your input in a table variable or Table-Valued parameter, then you can just use normal relational division techniques.
This then becomes a question of Relational Division With Remainder, with multiple divisors.
There are many ways to slice this cake. Here is one option
Join the filter input to the groups, to get each filter's group ID
Use a combination of DENSE_RANK and MAX to get the total distinct groups (you can't use COUNT(DISTINCT in a window function so we need to hack it)
You can change this step to use a subquery instead of window functions. It may be faster or slower
Join the main table, and filter out any ItemIDs which do not have their total distinct groups the same as the main total
SELECT
t1.ItemID
FROM (
SELECT *,
TotalGroups = MAX(dr) OVER ()
FROM (
SELECT
fi.FilterID,
t2.FilterGroupID,
dr = DENSE_RANK() OVER (ORDER BY t2.FilterGroupID)
FROM #Filters fi
JOIN Table2 t2 ON t2.FilterID = fI.FilterID
) fi
) fi
JOIN Table1 t1 ON t1.FilterID = fi.FilterID
GROUP BY
t1.ItemID
HAVING COUNT(DISTINCT FilterGroupID) = MAX(fi.TotalGroups);
db<>fiddle

Is there possibility to assign 0 for another occurence of the same user?

I have table like this:
And lets say I want to have in another occurence of login eg. 1234 i would like to have instead of 275 value of 0, the same for 3678 instead of 300 i would like to have 0. I want to have profit/loss only for first occurence in the table. Is this somehow possible to do it in SQL?
If you only want to keep the highest / lowest, you can join the table with itself.
If you only want the first (as in lowest row number) occurance you can use a window function and update all occurances > 1
UPDATE SUB
set profit = 0
FROM (
SELECT
profit,
ROW_NUMBER() OVER (PARTITION BY Login ORDER BY Login) as cnt
FROM table
) SUB
WHERE SUB.cnt > 1
In Standard SQL, you can use:
update t
set profit = 0
where profit > (select max(profit) from t t2 where t2.login = t.login);
Note that specific databases may have alternative ways to writing this. However, your question does not have a database tag.
Also, this assumes that your table does not have duplicates. Unfortunately, duplicates would be problematic if these are the only two columns in the table.

Filtering a column based on having some value in one of the rows in SQL or Presto Athena

I am trying in Athena to output only users which have some specific value in them but not in all of the rows
Suppose I have the table below.
I want all users which have value '100' in at least one of their rows but also having in other rows value different than 100.
user | value
A | 1
B | 2
A | 100
D | 3
A | 4
C | 3
C | 5
D | 100
So in this example I would want to get only users A and D because only them having 100 and none 100.
I tried maybe grouping by user and creating an array of values per user and then checking if array contains 100 but I don't manage doing it presto.
Also I thought about converting rows to columns and then checking if one of columns equals 100.
Those solutions are too complex? Anybody knows how to implement them or anyone has a better simpler solution?
The users that have at least one value of 100 can be found with this SQL:
SELECT DISTINCT user
FROM some_table
WHERE value = 100
But I assume you are after all tuples of user and value where the user has at least one value of 100, this can be accomplished by using the query above in a slightly more complex query:
WITH matching_users AS (
SELECT DISTINCT user
FROM some_table
WHERE value = 100
)
SELECT user, value
FROM matching_users
LEFT JOIN some_table USING (user)
You can use sub query as below to achieve your required output=
SELECT * FROM your_table
WHERE User IN(
SELECT DISTINCT User
FROM your_table
WHERE Value = 100
)
If you just want the users, I would go for aggregation:
select user
from t
group by user
having sum(case when value = 100 then 1 else 0 end) > 0;
If 100 is the maximum possible value, this can be simplified to:
having max(value) = 100

How do I display grouped ID's as a list with their respective values?

How do I not get all the ID's grouped, but instead listed from first to last; with all their respective values in the columns next to them?
Instead of grouping it, it should show ID 1 and its value, ID 2 and its value. EVEN if the values for the ID is the same. I tried removing the GROUP_CONCAT, but then it's only showing one ID per customfield_value?
SELECT GROUP_CONCAT(virtuemart_product_id), customfield_value, COUNT(*) c
FROM jos_virtuemart_product_customfields
WHERE virtuemart_custom_id = 6
GROUP BY customfield_value
HAVING c > 1
It's working currently, but grouping the ID's and spacing them with a comma. Should just display as in a normal table/list format.
Currently it shows like this(as you can see, it's ALL the same ICOS number, but different ID's. I ONLY need to display the values WHERE the ICOS NUMBER is "duplicate"):
ID ICOS Count
1,2,3 775896 3
It should be displaying like this:
ID ICOS Count
1 775896 1
2 775896 1
3 775896 1
All rows where the customfield_value is not unique:
-- Assuming MySQL
SELECT virtuemart_product_id, customfield_value
, COUNT(*) c -- maybe not needed
FROM jos_virtuemart_product_customfields
WHERE virtuemart_custom_id = 6
AND customfield_value IN
( SELECT customfield_value
FROM jos_virtuemart_product_customfields
WHERE virtuemart_custom_id = 6
GROUP BY customfield_value
HAVING COUNT(*) > 1 -- more than one row exists
)
GROUP BY virtuemart_product_id, customfield_value -- maybe not needed
If the virtuemart_product_id is unique you don't need the outer count/group by as it will always be 1.

SQL: Select Top 2 Query is Excluding Records with more than 2 Records

I just joined after having a problem writing a query in MS Access. I am trying to write a query that will pull out the first two valid samples in from a list of replicated sample results and then would like to average the sample values. I have written a query that does pull samples with only two valid samples and averages these values. However, my query doesn't pull samples where there are more than two valid sample results. Here's my query:
SELECT temp_platevalid_table.samp_name AS samp_name, avg (temp_platevalid_table.mean_conc) AS fin_avg, count(temp_platevalid_table.samp_valid) AS sample_count
FROM Temp_PlateValid_table
WHERE (Temp_PlateValid_table.id In (SELECT TOP 2 S.id
FROM Temp_PlateValid_table as S
WHERE S.samp_name = S.samp_name and s.samp_valid=1 and S.samp_valid=1
ORDER BY ID))
GROUP BY Temp_PlateValid_table.samp_name
HAVING ((Count(Temp_PlateValid_table.samp_valid))=2)
ORDER BY Temp_PlateValid_table.samp_name;
Here's an example of what I'm trying to do:
ID Samp_Name Samp_Valid Mean_Conc
1 54d2d2 1 15
2 54d2d2 1 20
3 54d2d2 1 25
The average mean_conc should be 17.5, however, with my current query, I wouldn't receive a value at all for 54d2d2. Is there a way to tweak my query so that I get a value for samples that have more than two valid values? Please note that I'm using MS Access, so I don't think I can use fancier SQL code (partition by, etc.).
Thanks in advance for your help!
Is this what you want?
select pv.samp_name, avg(pv.value_conc)
from Temp_PlateValid_table pv
where pv.samp_valid = 1 and
pv.id in (select top 2 id
from Temp_PlateValid_table as pv2
where pv2.samp_name = pv.samp_name and pv2.samp_valid = 1
)
group by pv.samp_name;
You might need avg(pv.value_conc * 1.0).