How get specific rows in grouped result - sql

i need to group some data but because there are 4 store images , sql query return 4 result for every store. How can i get only one for a store by using sql query ?
select s.name,si.SHOP_IMG_PATH,count(*) amount from stab t
inner join shop s on (s.shop_id = t.shop_id)
inner join SHOP_IMG si on (s.shop_id= si.SHOP_ID)
where t.acct_id = 111 and t.CR_DATE >= sysDate - 1
group by s.name,si.SHOP_IMG_PATH
order by 3 desc,1 asc
As you see below image there a re 4 images so query can give random image

You are grouping by s.name, si.SHOP_IMG_PATH it will consider all possible combination of s.name, si.SHOP_IMG_PATH as separate you need to keep group by only s.name
Try this
SELECT a.NAME, a.PATH, a.AMOUNT
FROM (select
s.name AS 'NAME', si.SHOP_IMG_PATH AS 'PATH', count(*) AS 'AMOUNT',
ROW_NUMBER() OVER(PARTITION BY s.name
ORDER BY type si.SHOP_IMG_PATH) AS rk
from
stab t
inner join shop s on (s.shop_id = t.shop_id)
inner join SHOP_IMG si on (s.shop_id= si.SHOP_ID)
where t.acct_id = 111 and t.CR_DATE >= sysDate - 1
group by s.name
order by 3 desc,1 asc) a
WHERE a.rk = 1;
Alternative
You will get result but this is just a workaround and easy alternative to your problem but not a good one.
select s.name AS 'NAME', min(si.SHOP_IMG_PATH) AS 'PATH', count(*) AS 'AMOUNT',
from
stab t
inner join shop s on (s.shop_id = t.shop_id)
inner join SHOP_IMG si on (s.shop_id= si.SHOP_ID)
where t.acct_id = 111 and t.CR_DATE >= sysDate - 1
group by s.name
order by 3 desc,1 asc
This second query will return result as per your need

group by s.name, si.SHOP_IMG_PATH
You're telling it to differentiate them according to SHOP_IMG_PATH. Hence, it shows 4 results, one for each of those.
You'll have to drop SHOP_IMG_PATH from the select clause, if you won't let it use it.
Edit
Got your comment. What you're looking for is random aggregation. This is achieved diferently on different SQL engines. Google around for the one you're using.
If it's Oracle, as indicated by the question tag, here

I solved my problem by using below query,
select s.name,t.shop_id,(select min(SHOP_IMG_PATH) from SHOP_IMG si where shop_id =t.shop_id),count(*) amount from stab t
inner join shop s on (s.shop_id = t.shop_id)
where t.acct_id = 111 and t.CR_DATE >= sysDate - 1
group by s.name,t.shop_id
order by 4 desc,1 asc

Related

Make sum of num_importe by the entidad code sql

My code:
select distinct entidad, sum(cast(num_importe as float))
from envio_remesa
inner join remesa
on envio_remesa.id = remesa.envio_remesa_id
where remesa.envio_remesa_id = 3 and remesa.tipo_doc='201';
The case is that for example I have two different "entidades"(suppose 18 and 21, but it can be any number), and I want to group in two different records the sum of the "num_importe" for the "entidad" 18, and the sum of the "num_importe" for the "entidad" 21.How could I do it?
What I want to come out:
entidad num_importe
18 92.300,00
21 56.000,20
432 120.000,32
12 12.232,12
you shoud use group by (by the way, distinct is useless here)
select entidad, sum(cast(num_importe as float))
from envio_remesa
inner join remesa
on envio_remesa.id = remesa.envio_remesa_id
where remesa.envio_remesa_id = 3 and remesa.tipo_doc='201'
group by entidad;
You can use aggregation:
select entidad, sum(cast(num_importe as float))
from envio_remesa er inner join
remesa r
on er.id = r.envio_remesa_id
where r.envio_remesa_id = 3 and r.tipo_doc = '201'
group by entidad;
Note: You should qualify entidad and num_importe so it is clear what table they come from.
Also, I added table aliases into the query. They make the query easier to write and to read.

How to check more than one unrelated conditions in SQL?

I have following query:
SQL> SELECT DISTINCT INSTRUCTORADDRESSMODPER.instructor_id, Instructor.instructor_name, InstructorRank.salary, Student.specification_id
2 FROM INSTRUCTORADDRESSMODPER
3 JOIN Student ON INSTRUCTORADDRESSMODPER.student_id = Student.student_id
4 JOIN Instructor ON INSTRUCTORADDRESSMODPER.instructor_id = Instructor.instructor_id
5 JOIN InstructorRank ON Instructor.instructor_rank = InstructorRank.instructor_rank
6 ORDER BY specification_id;
which has yielded following result:
I was trying to get result which shows same column values for instructors with same salary and same specification as highlighted in the figure. Now these two conditions require completely different checks and I don't even know how to get started.
You need something like this ?
SELECT instructor_id, instructor_name, instructor_name, specification_id
FROM (
SELECT DISTINCT INSTRUCTORADDRESSMODPER.instructor_id, Instructor.instructor_name, InstructorRank.instructor_name, Student.specification_id
, COUNT(distinct INSTRUCTORADDRESSMODPER.instructor_id)over(partition by InstructorRank.salary, Student.specification_id) cnt
FROM INSTRUCTORADDRESSMODPER
JOIN Student ON INSTRUCTORADDRESSMODPER.student_id = Student.student_id
JOIN Instructor ON INSTRUCTORADDRESSMODPER.instructor_id = Instructor.instructor_id
JOIN InstructorRank ON Instructor.instructor_rank = InstructorRank.instructor_rank
ORDER BY specification_id
)
WHERE cnt > 1
;
You can use the window function count as follows:
Select * from
(SELECT DISTINCT INSTRUCTORADDRESSMODPER.instructor_id, Instructor.instructor_name, InstructorRank.salary, Student.specification_id,
Count(1) over (partition by InstructorRank.salary, Student.specification_id) as cnt
FROM INSTRUCTORADDRESSMODPER
JOIN Student ON INSTRUCTORADDRESSMODPER.student_id = Student.student_id
JOIN Instructor ON INSTRUCTORADDRESSMODPER.instructor_id = Instructor.instructor_id
JOIN InstructorRank ON Instructor.instructor_rank = InstructorRank.instructor_rank)
Where cnt > 1
ORDER BY specification_id;
SQL> SELECT DISTINCT INSTRUCTORADDRESSMODPER.instructor_id,
Instructor.instructor_name,InstructorRank.salary, Student.specification_id
FROM INSTRUCTORADDRESSMODPER
WHERE 1=1
AND INSTRUCTORADDRESSMODPER.student_id = Student.student_id
AND INSTRUCTORADDRESSMODPER.instructor_id = Instructor.instructor_id
AND Instructor.instructor_rank = InstructorRank.instructor_rank
AND ORDER BY specification_id
AND ...;
With the above use, desired conditions can be added.

How to use 1 SQL query related to date and time in order to compare value difference

SELECT c.treatment_category, a.treatment_id, MAX(a.counts - b.counts) AS ReviewDifference
FROM
(SELECT treatment_id, COUNT(treatment_id) AS counts
FROM review
WHERE DATE(review.created) BETWEEN DATE(TIMESTAMP'2016-01-01 00:00:00.0') AND DATE(TIMESTAMP'2016-12-31 23:59:59.999')
GROUP BY treatment_id) a
LEFT JOIN
(SELECT treatment_id, COUNT(treatment_id)
FROM review
WHERE DATE(review.created) BETWEEN DATE(TIMESTAMP'2015-01-01 00:00:00.0') AND DATE(TIMESTAMP'2015-12-31 23:59:59.999')
GROUP BY treatment_id) b
ON a = b
LEFT JOIN
(SELECT t.treatment_category AS category, r.treatment_id AS number
FROM treatment t
LEFT JOIN review r
ON t.treatment_id = r.treatment_id
GROUP BY category, number) c
ON b.treatment_id = c.number
GROUP BY a.treatment_id, c.treatment_category
ORDER BY ReviewDifference DESC
LIMIT 1;
I need some hints or simpler query on how to do this question since it is related to date and time. Thank you.
What treatment category has seen the biggest increase in reviews from 2015 to 2016?
Please see below for the tables.
I have provided my code snippet and I would like to find a simpler and cleaner way on writing the code.
SELECT t.treatment_id, t.treatment_name,
COUNT( CASE WHEN YEAR(created) = 2016 THEN r.review_id END)
- COUNT( CASE WHEN YEAR(created) = 2015 THEN r.review_id END) as review_count
FROM treatments t
JOIN reviews r
ON t.treatment_id = r.treatment_id
GROUP BY t.treatment_id, t.treatment_name,
ORDER BY review_count DESC

Combine multiple rows with same value into one row in oracle

I have been trying to solve an Oracle SQL query but to no avail and was hoping i could get some assistance. The scenario is that am querying the database and i get multiple records with the same value and wanted to combine the multiple rows into one.What i want to achieve is have the record for customer with IDNO=22099575 in one row instead of three as it appears in the attached screen shot of my result from my query below
SELECT concat(cu.firstname,cu.secondname)
Customername,cu.customerno,l.idnumber Idno,l.branch_code
Branchcode,l.phonenumber
Phone,cu.gender,l.grade,l.arocode,l.loanaccount,l.duedate,l.interest,
l.outstandingamount Outstandingloanbal,
l.lien Lienamount,TO_CHAR(l.applicationdate,'DD-MM-YY')
applicationdate,l.lastpaymentdate Lastcreditdate,l.inarrears
Principalloaninarrears,
l.rebate_amount Rebatepayable, l.empcode, l.disbursaldate, lt.description
Producttype,sum(l.amountdisbursed) Disbursedamt,
l.loanamount Principalamount,l.interest
Interestamount,l.flexi_refno,l.active
FROM ((ebank.tbloanaccount l
INNER JOIN ebank.tbcustomers cu ON l.customerno = cu.customerno)
INNER JOIN ebank.tbloantype lt ON l.productcode = lt.productcode)
where l.DISBURSED = '1'
group by concat(cu.firstname,cu.secondname), cu.customerno, l.idnumber,
l.branch_code, l.phonenumber,
cu.gender, l.grade, l.arocode, l.loanaccount,
l.duedate, l.interest, l.outstandingamount, l.lien,
TO_CHAR(l.applicationdate,'DD-MM-YY'),
l.lastpaymentdate, l.inarrears, l.rebate_amount, l.empcode, l.disbursaldate,
lt.description, l.loanamount, l.interest, l.flexi_refno, l.active order by
l.disbursaldate desc;
Here is a screen shot of my results from the above query:
you can use dense_rank on queries, to get latest due_date, outstanding loan.
SELECT concat(cu.firstname,cu.secondname)
Customername,cu.customerno,l.idnumber Idno,l.branch_code
Branchcode,l.phonenumber
Phone,cu.gender,l.grade,l.arocode,l.loanaccount, max(l.duedate) keep ( dense_rank first order by l.duedate desc ) duedate,l.interest,
max(l.outstandingamount) keep ( dense_rank first order by l.duedate desc ) Outstandingloanbal,
l.lien Lienamount,TO_CHAR(l.applicationdate,'DD-MM-YY')
applicationdate,l.lastpaymentdate Lastcreditdate,l.inarrears
Principalloaninarrears,
l.rebate_amount Rebatepayable, l.empcode, l.disbursaldate, lt.description
Producttype,sum(l.amountdisbursed) Disbursedamt,
l.loanamount Principalamount,l.interest
Interestamount,l.flexi_refno,l.active
FROM ((ebank.tbloanaccount l
INNER JOIN ebank.tbcustomers cu ON l.customerno = cu.customerno)
INNER JOIN ebank.tbloantype lt ON l.productcode = lt.productcode)
where l.DISBURSED = '1'
group by concat(cu.firstname,cu.secondname), cu.customerno, l.idnumber,
l.branch_code, l.phonenumber,
cu.gender, l.grade, l.arocode, l.loanaccount,
l.duedate, l.interest, l.outstandingamount, l.lien,
TO_CHAR(l.applicationdate,'DD-MM-YY'),
l.lastpaymentdate, l.inarrears, l.rebate_amount, l.empcode, l.disbursaldate,
lt.description, l.loanamount, l.interest, l.flexi_refno, l.active order by
l.disbursaldate desc;

most frequent occurence

I have a table with transactions and a statement that is giving out the most used creditcards. AMEX, VISA ...
SELECT CARDBRAND,
count(*) as cardused
from INFO c
left join paytb t
on c.CONT_ID = t.CONT_ID
GROUP BY CARDBRAND
ORDER BY 2 desc;
Now I want to add a column with the MERCHNAME of the shops that were most often found in a transaction with the creditcard:
CARDBRAND CARDUSED MERCHNAME
----------------------------------------
AMEX 182345 Gasstation
VISA 70943 ....
SELECT CARDBRAND
,count(*) as cardused
,MERCHNAME
FROM INFO c
LEFT JOIN paytb t
on c.CONT_ID = t.CONT_ID
GROUP BY CARDBRAND,
MERCHNAME
ORDER BY count(*) desc;
suggestion: It is always recommended to use the ColumnName or function in this case in the ORDERBY clause rather than the column number to avoid any confusion.
First, your correct query should be:
select c.cardbrand, count(t.cont_id) as cardused
from info c left join
paytb t
on c.cont_id = t.cont_id
group by c.cardbrand;
Otherwise, you will never get "0" for card brands that are not used.
For the merchant information, you can use window functions:
select cardbrand, total_cardused, merchant
from (select c.cardbrand, t.merchant, count(t.cont_id) as cardused,
sum(count(t.cont_id)) over (partition by c.cardbrand) as total_cardused,
row_number() over (partition by c.cardbrand order by count(t.cont_id) desc) as seqnum
from info c left join
paytb t
on c.cont_id = t.cont_id
group by c.cardbrand, t.merchant
) cm
where seqnum = 1
group by c.cardbrand;