Select one value if two are present - sql

I have a table with, let's say, 3 columns: Store, Product, Status
Table, in some cases, returns 2 rows for one store and product but with different status:
Store Product Status
120 255 SYSTEM
120 255 USER
What I want to do is to get a row with USER if both are present (USER and SYSTEM), but if only one Status is present, I want to get a present one.
Any ideas?

One way is to use grouping and the max aggregate function:
select store, product, max(status) as status
from t
group by store, product;
This will get you the only present row if there's only one, or if there is both USER and SYSTEM present in the group you will get the USER row(s) (as USER is sorted after SYSTEM).

SELECT Store, Product, Status
FROM TABLE T1
WHERE 1 = (SELECT COUNT(*) FROM TABLE T2
WHERE T1.STORE = T2.STORE AND T1.PRODUCT= T2.PRODUCT)
UNION
SELECT Store, Product, Status
FROM TABLE T1
WHERE 1 < (SELECT COUNT(*) FROM TABLE T2
WHERE T1.STORE = T2.STORE AND T1.PRODUCT= T2.PRODUCT)
AND STATUS = 'USER'

This will work
SELECT TOP 1
Store ,
Product,
Status,
FROM
YourTable
ORDER BY CASE WHEN Status = 'USER' THEN 0 ELSE 1 END

Related

Count on Table 1 based on Count with Clause on Table 2, sql

Table 1
Table 2
I need to find the Count of total number of unique stores that have "Achieved Date" not Null that achieved all of the "Achievement Ids" "enabled" on Table 2.
So far I can find the count of stores that achieved a hard coded number, but I'm not breaking through the part where I use the Count of Enabled Ids on table 2 to define what the number is.
SELECT
COUNT(*) AS count
FROM
(SELECT
StoreNumber, COUNT(*) as Achievements
FROM
StoreAchievementProgress
WHERE
AchievedDate IS NOT NULL
GROUP BY
StoreNumber) count
maybe this query
SELECT S.StoreNumber
FROM StoreAchievementProgress S
RIGHT JOIN (SELECT Id FROM Table2 WHERE Enabled=1 )T
ON T.Id=S.AchievementId
AND AchievedDate IS NOT NULL
GROUP BY S.StoreNumber
HAVING COUNT(1) = (SELECT COUNT(Id) FROM Table2 WHERE Enabled=1 )
Joining the stores with a count of their enabled achievements to how many they can get
SELECT COUNT(*) AS StoresFullAchievements
FROM
(
SELECT p.StoreNumber, COUNT(*) AS TotalEnabledAchievements
FROM StoreAchievementProgress p
JOIN Achievements a ON a.id = p.AchievementId
WHERE p.AchievedDate IS NOT NULL
AND a.Enabled = 1
GROUP BY p.StoreNumber
) AS s
JOIN
(
SELECT COUNT(*) AS TotalEnabled
FROM Achievements
WHERE Enabled = 1
) a
ON a.TotalEnabled = s.TotalEnabledAchievements

SQL Count of two values in one column

I have a table with customer name and Status columns. The status column has two values
Test
Live
The customers appear more than once and can be classed as either test, live or BOTH like below:
**Customer | Status**
Logistics | Test
Logistics | Live
Ample | Live
What I want is a query to give me a count of the number of distinct customers who fall under both statuses. So using the above table, I would count customer logistics (since it has both test and live) but not ample (since it is just live).
Any ideas?
You can use group by clause :
select Customer, count(*)
from table t
group by Customer
having min(status) <> max(status);
If you want it with specific status then include where clause :
select Customer, count(*)
from table t
where status in ('Test', 'Live')
group by Customer
having count(distinct status) = 2;
EDIT : If you want other columns too, then i would prefer :
select t.*
from table t
where exists (select 1 from table t1 where t1.Customer = t.Customer and t1.status <> t.status);
try something like this:
select customer
from
(select customer, max(IsTest) as IsTest , max(IsLive) as IsLive
from
(select customer,
case when status='test' then 1 else 0 end as IsTest,
case when status='live' then 1 else 0 end as IsLive
from table) a
group by customer) b
where IsTest = 1 and IsLive = 1
you can use group by clause to get your desire output.
select Customer, count(*)
from table t
group by Customer
having min(status) <> max(status);

Postgresql selecting specific set of records based on a field value

I have postgresql data-set as shown below where a app_id may have multiple record. I need to select all the records for each app_id where bool_flag is true and if a app_id has no records with bool_flag value equal true then pick all records with false value for that app.
Here is the link to available data set
data-set
and this is the desired output I am looking for, thanks in advance.
desired output
Here is one method:
select t.*
from t
where t.bool_flag
union all
select t.*
from t
where not t.bool_flag and
not exists (select 1
from t t2
where t2.app_id = t.app_id and t2.bool_flag
);
As the description states, it starts by getting all rows with "true". It then gets the "false" rows where there is no corresponding "true" row.
One way to do it with count window function.
select app_id,created_date,bool_flag
from (select t.*
,count(case when not bool_flag then 1 end) over(partition by app_id) as false_cnt
,count(*) over(partition by app_id) as total
from tbl t
) t
where bool_flag or total=false_cnt
Another way with bool_or.
select t1.*
from (select app_id,bool_or(bool_flag) as bool_res
from tbl
group by app_id
) t
join tbl t1 on t.app_id=t1.app_id
where t.bool_res=t1.bool_flag

select multiple records based on order by

i have a table with a bunch of customer IDs. in a customer table is also these IDs but each id can be on multiple records for the same customer. i want to select the most recently used record which i can get by doing order by <my_field> desc
say i have 100 customer IDs in this table and in the customers table there is 120 records with these IDs (some are duplicates). how can i apply my order by condition to only get the most recent matching records?
dbms is sql server 2000.
table is basically like this:
loc_nbr and cust_nbr are primary keys
a customer shops at location 1. they get assigned loc_nbr = 1 and cust_nbr = 1
then a customer_id of 1.
they shop again but this time at location 2. so they get assigned loc_nbr = 2 and cust_Nbr = 1. then the same customer_id of 1 based on their other attributes like name and address.
because they shopped at location 2 AFTER location 1, it will have a more recent rec_alt_ts value, which is the record i would want to retrieve.
You want to use the ROW_NUMBER() function with a Common Table Expression (CTE).
Here's a basic example. You should be able to use a similar query with your data.
;WITH TheLatest AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY group-by-fields ORDER BY sorting-fields) AS ItemCount
FROM TheTable
)
SELECT *
FROM TheLatest
WHERE ItemCount = 1
UPDATE: I just noticed that this was tagged with sql-server-2000. This will only work on SQL Server 2005 and later.
Since you didn't give real table and field names, this is just psuedo code for a solution.
select *
from customer_table t2
inner join location_table t1
on t1.some_key = t2.some_key
where t1.LocationKey = (select top 1 (LocationKey) as LatestLocationKey from location_table where cust_id = t1.cust_id order by some_field)
Use an aggregate function in the query to group by customer IDs:
SELECT cust_Nbr, MAX(rec_alt_ts) AS most_recent_transaction, other_fields
FROM tableName
GROUP BY cust_Nbr, other_fields
ORDER BY cust_Nbr DESC;
This assumes that rec_alt_ts increases every time, thus the max entry for that cust_Nbr would be the most recent entry.
By using time and date we can take out the recent detail for the customer.
use the column from where you take out the date and the time for the customer.
eg:
SQL> select ename , to_date(hiredate,'dd-mm-yyyy hh24:mi:ss') from emp order by to_date(hiredate,'dd-mm-yyyy hh24:mi:ss');

Select a NON-DISTINCT column in a query that return distincts rows

The following query returns the results that I need but I have to add the ID of the row to then update it. If I add the ID directly in the select statement it will return me more results then I need because each ID is unique so the DISTINCT statement see the line as unique.
SELECT DISTINCT ucpse.MemberID, ucpse.ProductID, ucpse.UserID
FROM UserCustomerProductSalaryExceptions as ucpse
WHERE EXISTS (SELECT NULL
FROM UserCustomerProductSalaryExceptions as upcse2
WHERE ucpse.userid = upcse2.userid AND ucpse.MemberID = upcse2.MemberID AND ucpse.ProductID = upcse2.ProductID
GROUP BY upcse2.UserID, upcse2.memberid, upcse2.productid
HAVING COUNT(UserID) >= 2
)
So basically I need to add ucpse.ID in the Select statement while keeping DISTINCT values for MemberID,ProductID and UserID.
Any Ideas ?
Thank you
According to you comment:
If the data has been duplicated 67 times for a given employee with a given product and a given client, I need to keep only one of thoses records. It's not important which one, so this is why I use DISTINC to obtain unique combinaison of given employee with a given product and a given client.
You can use MIN() or MAX() and GROUP BY instead of DISTINCT
SELECT MAX(ucpse.ID) AS ID, ucpse.MemberID, ucpse.ProductID, ucpse.UserID
FROM UserCustomerProductSalaryExceptions as ucpse
WHERE EXISTS (SELECT NULL
FROM UserCustomerProductSalaryExceptions as upcse2
WHERE ucpse.userid = upcse2.userid AND ucpse.MemberID = upcse2.MemberID AND ucpse.ProductID = upcse2.ProductID
GROUP BY upcse2.UserID, upcse2.memberid, upcse2.productid
HAVING COUNT(UserID) >= 2
)
GROUP BY ucpse.MemberID, ucpse.ProductID, ucpse.UserID
UPDATE:
From you comments I think the below query is what you need
DELETE FROM UserCustomerProductSalaryExceptions
WHERE ID NOT IN ( SELECT MAX(ucpse.ID) AS ID
FROM #UserCustomerProductSalaryExceptions
GROUP BY ucpse.MemberID, ucpse.ProductID, ucpse.UserID
HAVING COUNT(ucpse.ID) >= 2
)
If all you want is to delete the duplicates, this will do it:
WITH X AS
(SELECT ID,
ROW_NUMBER() OVER (PARTITION BY MemberID, ProductID, UserID ORDER BY ID) AS DupRowNum<br
FROM UserCustomerProductSalaryExceptions
)
DELETE X WHERE DupRowNum > 1
ID's not necessary - try:
UPDATE uu SET
<your settings here>
FROM UserCustomerProductSalaryExceptions uu
JOIN ( <paste your entire query above here>
) uc ON uc.MemberID=uu.MemberId AND uc.ProductID=uu.ProductId AND uc.UserID=uu.UserId
From the sound of your data structure (which I would STRONGLY advise normalizing as soon as possible), it sounds like you should be updating all the records. It sounds as if each duplicate is important because it contains some information about an employee's relation to a customer or product.
I would probably update all the records. Try this:
UPDATE UCPSE
SET
--Do your updates here
FROM UserCustomerProductSalaryExceptions as ucpse
JOIN
(
SELECT UserID, MemberID, ProductID
FROM UserCustomerProductSalaryExceptions
GROUP BY UserID, MemberID, ProductID
HAVING COUNT(UserID) >= 2
) T
ON ucpse.UserID = T.UserID AND ucpse.MemberID = T.MemberID AND ucpse.ProductID = T.ProductID