select records as a single with different queries - mysql

I have a table, the table structure of which is as follows
id service_type pincode
---------------------------------
1 B 695582
2 D 676102
3 P 685584
4 B 685608
I will get two different pincodes from the front end. say for example 695582 and 685608. I need to get the service_types at these pincodes with single query and the results should be a single row. I have tried a UNION query, but the results are in two different row.
select 'buyer' name, service_type from tm_location_carrier_lnk where pincode=695582
UNION
select 'seller' name, service_type from tm_location_carrier_lnk where pincode=685608
The result of the above query is as follows
name service_type
------------------
buyer B
seller B
How can i get results in a single row as follows
Buyer Seller
B B

Why not doing
SELECT (select service_type from tm_location_carrier_lnk where pincode=695582 LIMIT 1) as Buyer, (select service_type from tm_location_carrier_lnk where pincode=685608 LIMIT 1) as Seller;
Here you can find a working example: http://sqlfiddle.com/#!9/e01426/1
edit: added LIMIT 1 for avoiding duplicated pincodes.

One solution assuming unique pincodes and specific to your request:
Select
(select max(service_type)
from tm_location_carrier_lnk
where pincode=695582) as Buyer
, (select max(service_type)
from tm_location_carrier_lnk
where pincode=685608) as Seller;

Related

MYSQL count multiple orders without grouping

I'm trying to produce a query that shows every order AND adds an additional column which shows if the customer has previously placed an order by NAME, ADDRESS or USER_ID, without grouping results.
I've tried:
SELECT *, COUNT(`NAME`) c FROM `salesorders` GROUP BY `NAME` HAVING c > 0
This shows all customer orders, however if the customer has previously ordered before, the customers name only shows once due to the grouping.
e.g.
Name, Date, Previous_Orders
John Smith, 2019-11-28, 2
Lisa Thomas, 2019-11-20, 1
I would like it show both occurrences:
John Smith, 2019-11-28, 2
Lisa Thomas, 2019-11-20, 1
John Smith, 2019-05-07, 2
salesorders columns;
Name
User_ID
Date
Lets say the new column is Previous_Orders
For MariaDB 10.4.6 you can use COUNT() window function:
select *,
count(full_add) over (partition by full_add) Previous_Orders
from salesorders;
If the column Name is unique, then you can replace user_id with Name if you prefer.
If by Previous_Orders you mean the number of orders up to the date in the current row, then change to:
select *,
count(full_add) over (partition by full_add order by date) Previous_Orders
from salesorders;
See the demo.
You could use a join with the subquery for count group by name
SELECT s.*, t.c
FROM `salesorders` s
INNER JOIN
(SELECT name, COUNT(*) c
FROM salesorders
GROUP BY name) t ON t.name = s.name
WHERE t.c > 0

Select Min and Max value

I have a table called 'customers':
id | name | age
1 | john | 35
2 | paul | 22
3 | ana | 26
4 | mark | 19
5 | jack | 29
i want to select the name and max age, the name and min age... something like:
john 35 mark 19
is it possible?
The below query will give you the min and max on one row as requested. If there are multiple matches for min/max you will get multiple rows. Depending on the SQL engine you use, the syntax to limit to one row is different.
SELECT cMax.Name, cMax.Age, cMin.Name, cMin.Age
FROM customers cMin
JOIN customers cMax ON
cMax.Age = (SELECT MAX(Age) FROM customers)
WHERE cMin.Age = (SELECT MIN(Age) FROM customers)
There are different types of joins (e.g. INNER, OUTER, CROSS); however, for your question it doesn't much matter which you use.
Yes, you can do it,
select name, age from customers
where age in (select max(age)
from customers union select min (age)from customers)
try this
select name, age from customers where age=(select max(age) from customers) union
select name, age from customers where age=(select min(age) from customers)
If you want them on the same row:
select cmin.*, cmax.*
from (select name, age as minage
from customers
order by age asc
fetch first 1 row only
) cmin cross join
(select name, age as maxage
from customers
order by age desc
fetch first 1 row only
) cmax;
fetch first 1 row only is standard syntax for returning only the first row of the result set. Some databases have bespoke syntax, such as limit or select top (1).
Try using this query to show MAX age:-
select * from customers where age=(select max(age) from customers);
To show MIN age use the below Query:-
select * from customers where age=(select min(age) from customers);
You could use a cross join, which will put the two query ouputs next to one another. Building off Rodrigo's queries:
select
max_cust.name,
max_cust.age,
min_cust.name,
min_cust.age
from (select name, age from customers where age=(select max(age) from customers)) as max_cust
cross join (select name, age from customers where age=(select min(age) from customers)) as min_cust
It's maybe not the most performant but it gets the right shape. Be wary of cross joins when the tables don't have exactly 1 row, as it creates a cartesian product of the rows in the tables being joined.

Display column values and their count on SQL

I just want to ask you please this question on SQL.
Let's consider this EMPLOYEE table :
Employee Department
A 10
A 10
A 11
A 12
B 13
B 13
What I want to display is for each employee, all distinct departments (without duplicates) AND the total number of those distinct departments. So, something like this :
Employee Department total_dept
A 10 3
A 11 3
A 12 3
B 13 1
If possible, I would even prefer something like these :
Employee Department total_dept
A 10 3
A 11 null
A 12 null
B 13 1
I have a very big table (with many columns and many data) so I thought this can be an "optimisation", no ? I mean, there is no need to store the total_dept in all rows. Just put it once it's sufficient. No problem if after this I left the column empty. But I don't know if it's possible to do such thing in SQL.
So, how can I fix this please ? I tried but it seems impossible to combine count(column) with the same column...
Thank you in advance
This might be what you are looking for
SELECT
emp,
dept,
(select count(distinct dept) from TB as tbi where tb.emp = tbi.emp ) x
FROM TB
group by emp, dept;
MySQL 8.0 supports windowed COUNT:
SELECT *,COUNT(*) OVER (PARTITION BY Employee) AS total_dept
FROM (SELECT DISTINCT * FROM Employees) e
db<>fiddle demo
You could even have second resulset(I recommend to leave presentation matter to apllication layer):
SELECT *, CASE WHEN ROW_NUMBER() OVER(PARTITION BY Employee ORDER BY Department) = 1
THEN COUNT(*) OVER (PARTITION BY Employee) END AS total_dept
FROM (SELECT DISTINCT * FROM Employees) e
ORDER BY Employee, Department;
db<>fiddle demo
For the 2nd version:
SELECT
DISTINCT e.Employee, e.Department,
CASE
WHEN e.Department =
(SELECT MIN(Department) FROM Employees WHERE Employees.Employee = e.Employee)
THEN
(SELECT COUNT(DISTINCT Department) FROM Employees WHERE Employees.Employee = e.Employee)
END AS total_dept
FROM Employees e
ORDER BY e.Employee, e.Department;
See the demo

Select all type of data

My table is like:
id name seller product
1 bags s1 gold bag
2 shirt s1 shirts
3 shows s1 big show
4 jewellery s1 jewellery
5 Tv s2 Tv
I want to select 4 rows and in 4 rows must have seller s1 and s2 both results. Right now when I selecting 4 records so first 4 record are selecting that have seller s1
Edit
I have tried "GROUP BY" but its only returning single result.... I mean id=1
And
select distinct seller from table
getting only only 2 rows
I need
"I want to select 4 rows and in 4 rows must have seller s1 and s2 both results."
select distinct seller from table
though this will return only 2 rows
The following solution will return 4 rows which contain both sellers s1 and s2.
Code Segment 1
The code segment returns only 3 records for "s1". This is accomplished by adding the where seller = "s1" and limit 3 clause to the query.
select id, name, seller, product
from mytable
where seller = 's1'
limit 3
The union clause joins the two code segments together.
Code Segment 2
The second code segment performs a subquery similar to what was seen in the first code segment. The outer query was added to ensure the limit clause only restricted to the subquery and not to the entire result.
select *
from (
select id, name, seller, product
from mytable
where seller = 's2'
limit 1) t1
Here is the full code with link to SQL Fiddle demo.
select id, name, seller, product
from mytable
where seller = 's1'
limit 3
union
select *
from (
select id, name, seller, product
from mytable
where seller = 's2'
limit 1) t1

SQL: Get records that satisfy conditions coming from multiple records

Let's take a simple table that links customer IDs to product IDs if the customer bought a certain product. I'm looking for an SQL (MySQL) that lists all customers who bought specific products.
CustomerID ProductID
1 A // customer 1 bought product A
2 A
1 B
3 A
2 C
3 B
I would like to get a list of customers who bought both A and B (customers 1 and 3) and customers who bought A but not B (customer 2). I need to do this for more than 2 products, about up to 10, like "A and C and D but not B and E and F".
For question: get a list of customers who bought both A and B
SELECT CustomerID
FROM CustomerList
WHERE ProductID IN ('A', 'B')
GROUP BY CustomerID
HAVING COUNT(*) = 2
if uniqueness was not enforce on ProductID for every CustomerID, DISTINCT keyword is required,
SELECT CustomerID
FROM CustomerList
WHERE ProductID IN ('A', 'B')
GROUP BY CustomerID
HAVING COUNT(DISTINCT ProductID ) = 2
SQLFiddle Demo (both queries)
For the second question, "..A and C and D but not B and E and F"
SELECT CustomerID
FROM CustomerList
WHERE ProductID IN ('A', 'C', 'D')
GROUP BY CustomerID
HAVING COUNT(*) = 3 AND
CustomerID NOT IN
(
SELECT CustomerID
FROM CustomerList
WHERE ProductID IN ('B','E','F')
)
SQLFiddle Demo
TRy this::
Select DISTINCT CUSTOMERID from table1 where PRODUCTID='A'
Here's a slightly different approach for this one(test1 is your example table) :
Select customerId, group_concat(ProductId)
, case when (group_concat(ProductId) like '%A%' and group_concat(ProductId) like '%B%') then 'Bought A&B'
when (group_concat(ProductId) like '%A%' and group_concat(ProductId) not like '%B%') then 'Bought A only' end as Flag
from test1
group by customerId
JW's answer works perfectly, I'd just like to make a small addition. I used a simplified example in the question, in the original case the filtering happens on several joined tables. Taking that to this simple example it basically means that ProductID can be NULL. The query works, but runs for 2 minutes. It seems the cause is a MySQL query optimization bug. Changing the subquery condition to
WHERE ProductID IS NOT NULL and ProductID IN('B','E','F')
reduced query time to two seconds.