SQL if condition true, count only once - mysql

I have a table with three columns: Name, Country, Price and I need a SQL query that creates a fourth Boolean column named Qualify. This column needs to be true if Price<100 and there is no other row with price<100 and the same country.
Example:
Name - Country- Price- Qualify
Daniel - ES - 98 - TRUE
John - PT - 45 - TRUE
Maria - UK - 102 - FALSE
Anna - PT - 31 - FALSE (because there is already a row with PT and Price<100)
Joseph - UK - 25 - TRUE
Miriam -DK - 105 - FALSE
All this is because I do not want to count volumes more than one time if the price is under 100 and the country is the same. Is this even possible? Thanks

Think exists. In MySQL, you don't even need a case expression:
select t.*,
(t.price < 100 and
not exists (select 1
from t t2
where t2.country = t.country and t2.name <> t.name and t2.price < 100
)
) as flag
from t;
This assumes that name is unique, at least with respect to country.

Just providing another option using CASE statement:
Select
#row_number:=CASE
WHEN #country = Country AND Price < 100 AND #price < 100
THEN 1
ELSE 0 END AS Qualify,
#country:= Country As Country,
#price:= Price As Price
FROM
Test
ORDER BY Country, Price
Here is the demo

Related

configure query to bring rows which have more than 1 entries

How to get those entries which have more than 1 records?
If it doesn't make sense... let me explain:
From the below table I want to access the sum of the commission of all rows where type is joining and "they have more than 1 entry with same downmem_id".
I have this query but it doesn't consider more entries scenario...
$search = "SELECT sum(commission) as income FROM `$database`.`$memcom` where type='joining'";
Here's the table:
id mem_id commission downmem_id type time
2 1 3250 2 joining 2019-09-22 13:24:40
3 45 500 2 egbvegr new time
4 32 20 2 vnsjkdv other time
5 23 2222 2 vfdvfvf some other time
6 43 42 3 joining time
7 32 353 5 joining time
8 54 35 5 vsdvsdd time
Here's the expected result: it should be the sum of the id no 2, 7 only
ie. 3250+353=whatever.
It shouldn't include id no 6 because it has only 1 row with the same downmem_id.
Please help me to make this query.
Another approach is two levels of aggregation:
select sum(t.commission) income
from (select sum(case when type = 'joining' then commission end) as commission
from t
group by downmem_id
having count(*) > 1
) t;
The main advantage to this approach is that this more readily supports more complex conditions on the other members of each group -- such as at most one "joining" record or both "joining" records and no more than two "vnsjkdv" records.
Use EXISTS:
select sum(t.commission) income
from tablename t
where t.type = 'joining'
and exists (
select 1 from tablename
where id <> t.id and downmem_id = t.downmem_id
)
See the demo.
Results:
| income |
| ----- |
| 3603 |
You can use subquery that will find all downmem_id having more than one occurrence in the table.
SELECT Sum(commission) AS income
FROM tablename
WHERE type = 'joining'
AND downmem_id IN (SELECT downmem_id
FROM tablename t
GROUP BY downmem_id
HAVING Count(id) > 1);
DEMO

MySQL - add column to table and insert "tag" if order is from new customer

I have simple table:
Order_ID Client_ID Date Order_Status
1 1 01/01/2015 3
2 2 05/01/2015 3
3 1 06/01/2015 3
4 2 10/01/2015 3
5 1 12/01/2015 4
6 1 05/02/2015 3
I want to identify orders from new customers which are orders in same month in which that customer made first order with Order_Status = 3
So the output table should look like this:
Order_ID Client_ID Date Order_Status Order_from_new_customer
1 1 01/01/2015 3 yes
2 2 05/01/2015 3 yes
3 1 06/01/2015 3 yes
4 2 10/01/2015 3 yes
5 1 12/01/2015 4 NULL
6 1 05/02/2015 3 no
I wasn't able to successfully figure out the query. Thanks a lot for any help.
Join with a subquery that gets the date of the first order by each customer.
SELECT o.*, IF(MONTH(o.date) = MONTH(f.date) AND YEAR(o.date) = YEAR(f.date),
'yes', 'no') AS order_from_new_customer
FROM orders AS o
JOIN (SELECT Client_ID, MIN(date) AS date
FROM orders
WHERE Order_Status = 3
GROUP BY Client_ID) AS f
ON o.Client_ID = f.Client_ID
Use a CASE statement along with a SELF JOIN like below
select t1.*,
case when t1.Order_Status = 3 and MONTH(t1.`date`) = 1 then 'yes'
when t1.Order_Status = 3 and MONTH(t1.`date`) <> 1 then 'no'
else null end as Order_from_new_customer
from order_table t1 join order_table t2
on t1.Order_ID < t2.Order_ID
and t1.Client_ID = t2.Client_ID;
If your order table gets big, the solutions from Rahul and Barmar will tend to get slow.
I would hope your shop will get many orders and you will run into performance trouble ;-). So I would suggest marking the very first order of a new customer with a tinyint column, and when you have the comfort of a tinyint, you could code it like:
0 : unknown
1 : very first order
2 : order in first month
3 : order in "grown-up" mode.
The very first order you could probably mark easily, everyone loves a bright new customer enough to store this event somehow during first ordering. The other orders you can identify in a background job / cronjob by there "0" for unknown, or you mark your old customers and store the "3" on their orders.
The result-set can be achieved without any table-join or subquery:
select
if(Order_Status<>3,null,if(#first_date:=if(#prev_client_id!=Client_ID,month(date),#first_date)=month(date),"yes","no")) as Order_from_new_customer
,Order_ID,Client_ID,date,Order_Status,#prev_client_id:=client_id
from
t1,
(select #prev_client_id:="",#first_date:="")t
order by Client_ID ,date
One extra column added for computation and order by clause is used.
Verify result at http://sqlfiddle.com/#!9/83c29f/24

Change Value based on previous rows in mysql

I have a table which has below structure. I'm using phpmyadmin 3.4.5, mysql version 5.5.16.
Table
Invoice_ID - PO_ID- Product - Quantity Invoice_Qty - Amount
Inv1 - PO1 - P1 - 100 - 50 - 1000
Inv2 - PO1 - P1 - 100 - 50 - 1000
Inv3 - PO2 - P2 - 50 - 20 - 500
Inv4 - PO2 - P2 - 50 - 20 - 500
Inv5 - PO2 - P3 - 50 - 10 - 250
What I'm really want to do is that
If Previous Row of PO_ID and and Product Name is
Same as current Row PO_ID and Product then Quantity of current row should be zero?
Sum of Invoice_Quantity = Quantity. So Required like below
My Expected Output given below:
Out Put:
Invoice_ID - PO_ID- Product - Quantity Invoice_Qty - Amount
Inv1 - PO1 - P1 - 100 - 50 - 1000
Inv2 - PO1 - P1 - 0 - 50 - 1000
Inv3 - PO2 - P2 - 50 - 20 - 500
Inv4 - PO2 - P2 - 0 - 20 - 500
Inv5 - PO2 - P3 - 0 - 10 - 250
I tried the How to get result set like Oracle lag function. But It not worked for me.
And tried to write a procedure for that. I'm stuck with export resutlset.
That is I don't know how to assign and get the result set.
Please help me out this problem.
Refer:
http://sqlfiddle.com/#!2/5c0b0/4
Your sqlfiddle was confusing. Please don't provide sample data here and then use different sample data in the sqlfiddle. And your desired result here is wrong, since you said in the description
If Previous Row of PO_ID and and Product Name is Same as current Row PO_ID and Product then Quantity of current row should be zero
Anyway, used my own...
select
t.*,
if(#previd = po_id and #prevprod = Product, 0, Quantity) AS new_quantity,
#previd := po_id,
#prevprod := product
from
t
, (select #previd:=null, #prevprod:=null) var_init
order by po_id, product
sqlfiddle
Note, that the order in the select clause is important, as well as the order by clause.
The previous ID is the maximum ID of all lower IDs. So the statement can be written as:
select
invoice_id, po_id, product,
case when mytable.po_id = prev_mytable.po_id and mytable.product = prev_mytable.product
then 0
else mytable.quantity
end as qty,
invoice_qty, amount
from mytable
left join mytable prev_mytable on prev_mytable.id =
(
select max(id)
from mytable all_prev_mytable
where all_prev_mytable.id < mytable.id
)
order by invoice_id;
And here is the SQL fiddle: http://sqlfiddle.com/#!2/5c0b0/11.
This is Standard SQL and should thus work with about any dbms.
this works :):) :
select Invoice_ID,PO_ID,product,
case when
decode(lead(Quantity) over (order by PO_ID),Quantity,'SAME','DIFF') = 'SAME'
then Quantity
else 0
end Quantity, Amount
from <table-name>

MySQL - Multiply column by value depending on that column

How can I write this.. I have table 'Company' with a column 'Size'. The size references enums. I need to display the average company size as alias AS 'AverageEstimatedCompanySize' by substituting column 'Size' when column 'Size' is:
1 = 15
2 = 30
3 = 50
4 = 100
5 = 250
In other words, my table shows company size as either 1, 2, 3, 4 or 5. While 1 is actually a company size of 15.
This is all part of a bigger query:
SELECT COUNT(DISTINCT(ID)) AS 'Total # of Opps', AVG(Size*?) AS 'AverageEstimatedCompanySize'
FROM persontable AS POJT INNER JOIN opportunity
ON POJT.ID = opportunity.id
WHERE opportunity.TimeStamp >= '2012-01-01' AND opportunity.TimeStamp <= '2012-12-31' AND POJT.JobTitleID IN
(SELECT Id
FROM job
WHERE CategoryID IN
(SELECT id
FROM job_category
WHERE name IN ('Sc', 'Ma', 'Co', 'En', 'Tr')))
Sounds like something solvable with a case statement. The following is untested but should point you in the right direction.
SELECT
COUNT(DISTINCT(ID)) AS 'Total # of Opps',
AVG(
CASE Size
WHEN 1 THEN 15
WHEN 2 THEN 30
WHEN 3 THEN 50
WHEN 4 THEN 100
WHEN 5 THEN 250
END
) AS 'AverageEstimatedCompanySize'
FROM persontable AS POJT INNER JOIN opportunity
ON POJT.ID = opportunity.id
WHERE opportunity.TimeStamp >= '2012-01-01' AND opportunity.TimeStamp <= '2012-12-31' AND POJT.JobTitleID IN
(SELECT Id
FROM job
WHERE CategoryID IN
(SELECT id
FROM job_category
WHERE name IN ('Sc', 'Ma', 'Co', 'En', 'Tr')))
I'm thinking that one approach might be to modify the query to JOIN to the Company table appropriately (that's something you'll need to work out), and then modify the AVG statement:
... AVG(CASE `Size`
WHEN 1 THEN 15
WHEN 2 THEN 30
WHEN 3 THEN 50
WHEN 4 THEN 100
WHEN 5 THEN 250 END) AS 'AverageEstimatedCompanySize'
where Size is from the Company table.
Now, a more dynamic approach would be to create a new field, or even a new table, that maps those sizes and just JOIN the Company table and say the new table in the query and just grab the appropriate field per row then. That would get rid of the CASE statement.

How to regroup records with different values in one SQL query

Let's say I have the following table :
Name - Country - Age
--------------------
Toto - Switzerland - 10
Titi - France - 12
Tata - Italy - 21
Tutu - England - 13
Tete - Italy - 14
I want to create a sql query as simple as possible to regroup people living in defined grouped countries like :
Group A = Switzerland + Italy
Group B = France + England
I don't know how to create a group withn my records with a column that could have multiple different values in the same group...
Could somebody help me with this ?
More information : SQL Server 2008 database.
You mean like this?
SELECT COUNT(Name), GroupA, GroupB FROM
(`SELECT Name, Country, Age,
Country='Switzerland' OR Country='Italy' As GroupA,
Country='France' OR Country='England' As GroupB)
Group By GroupA, GroupB
Select * from (select *,case when Country ='Switzerland' then 'A'
when Country ='Italy' then 'A'
when Country ='France' then 'B'
when Country ='England' then 'B'
else 'C' end) classification from table1)
order by classification
This will group the ppl as per your criteria. If this grouping is static you can have seprate table and use inner join. That will make query more readable