Fetching the rows from db table - mysql

Below is my db table.
RECORDNO| STAGE| COMMENT | STATE
12 | 1 | abcd | P
13 | 1 | adfg | P
14 | 2 | adsds | P
15 | 2 | defe | P
I want to fetch the records which has State'P' and stage = stage of minimum recordno ;
SELECT *
FROM history
WHERE STATE = 'P'
AND recordNO = ( SELECT MIN(record#)
FROM history
WHERE STATE = 'P' ) ;
The above query gives only the row with recordno 12. I want to fetch rows with recordno 12 and 13 .
Please help me with the query.

For MySql use this:
SELECT h.* FROM history h
WHERE h.STATE = 'P'
AND h.STAGE = (SELECT STAGE FROM history WHERE STATE = h.STATE ORDER BY RECORDNO LIMIT 1);
The subquery in the WHERE clause returns the stage of minimum recordno.
See the demo.
For Oracle 12c+ change LIMIT 1 with:
FETCH FIRST 1 ROWS ONLY
See the demo.
Results:
| RECORDNO | STAGE | COMMENT | STATE |
| -------- | ----- | ------- | ----- |
| 12 | 1 | abcd | P |
| 13 | 1 | adfg | P |

Oracle:
select * from history
where stage in
( select stage from history where recordno =
( select min(recordno) from history where state = 'P' )
);
Demo here

A subquery match for STAGE column with MINIMUM of STAGE
SELECT h1.*
FROM history h1
WHERE h1.STATE = 'P'
AND h1.STAGE = (SELECT MIN(STAGE) FROM history );
Or An Inline view through JOIN keyword
SELECT h1.*
FROM history h1
JOIN (SELECT MIN(STAGE) AS STAGE FROM history ) h2
ON h2.STAGE = h.STAGE
WHERE h1.STATE = 'P';
for both of the DBMS(MySQL&Oracle).

Related

MySQL Update table by matchig values in the same column

I have a table where I store data for different groups and I need to update one group if values in one column are matching.
the table looks like this:
prop_id | group_id | value | visible
1 | 1 | 10 | 1
1 | 2 | 10 | 1
1 | 3 | 15 | 1
2 | 1 | 10 | 1
2 | 2 | 10 | 1
2 | 3 | 10 | 1
So I want to set the visible column to 0 for the group_id=3 if the values in the value column are equal to group_id=1. In this case if value=10 for both group_id=1 and group_id=3 than set visible=0 for group_id=3
expected result after update
prop_id | group_id | value | visible
1 | 1 | 10 | 1
1 | 2 | 10 | 1
1 | 3 | 15 | 1
2 | 1 | 10 | 1
2 | 2 | 10 | 1
2 | 3 | 10 | 0
How is this possible?
Write it as a SELECT first.
Start simple, the rows that we want to update we know are group_id=3 and visible=1, so write a query that gets all of those rows:
SELECT g3.value
, g3.visible
FROM mytable g3
WHERE g3.group_id = 3
AND g3.visible = 1
We know the rows we want to update are in that set, but there are some additional conditions.
So we extend that. According to the spec, we need to find out if there are any matching group_id=1 rows that are visible=1 (matching on value).
We can do that check either with an EXISTS correlated subquery, or we can use a JOIN.
SELECT g3.group_id
, g3.value
, g3.visible
FROM mytable g3
WHERE g3.group_id = 3
AND g3.visible = 1
AND EXISTS ( SELECT 1
FROM mytable g1
WHERE g1.group_id = 1
AND g1.visible = 1
AND g1.value = g3.value
)
-or-
SELECT g3.group_id
, g3.value
, g3.visible
FROM mytable g3
JOIN mytable g1
ON g1.group_id = 1
AND g1.visible = 1
AND g1.value = g3.value
WHERE g3.group_id = 3
AND g3.visible = 1
Verify the query is returning the rows we want to update, under the specific conditions. (It is much easier to verify the results of a SELECT statement, and adjust as necessary, than it is an UPDATE statement.)
Once we have a SELECT query working and verified (returning the rows we want to update) we can convert it into an UPDATE statement. Replace the SELECT ... FROM with UPDATE and add a SET clause that is returning the rows
UPDATE mytable g3
JOIN mytable g1
ON g1.group_id = 1
AND g1.visible = 1
AND g1.value = g3.value
SET g3.visible = 0
WHERE g3.group_id = 3
AND g3.visible = 1
Use Self JOIN then UPDATE
You can try this.
UPDATE T t1
JOIN T t2 on t1.group_id = t2.group_id
and t1.rop_id<>t2.rop_id and t1.value > t2.value
SET t2.visible = 0
sqlfiddle:http://sqlfiddle.com/#!9/6f06de/1

Count (Select * Join) mysql query

I'm stuck on this for hours, I'm trying to COUNT how many subscribers are there in Group A, Group B, Group C for this particular query:
SELECT rh.id_subscriber, rh.bill_month, rh.bill_year,
(
SELECT tbl_gen_info.gen_data_03
FROM tbl_subscriber
LEFT JOIN tbl_gen_info ON tbl_subscriber.bill_area_code = tbl_gen_info.gen_data_01
WHERE rh.id_subscriber = tbl_subscriber.id_subscriber
) AS group_area
FROM tbl_reading_head AS rh
WHERE rh.id_soa_head IS NULL
AND rh.read_status <> 'Beginning'
AND rh.rec_status = 'active'
ORDER BY rh.id_subscriber
The sub-query gets the Group area gen_data_03 from tbl_gen_info
Tables contain this information:
tbl_gen_info
--------------------------------------------
| gen_category | gen_data_01 | gen_data_03 |
--------------------------------------------
| Area Code | Camacho St. | Group A |
--------------------------------------------
tbl_subscriber
----------------------------------
| id_subscriber | bill_area_code |
----------------------------------
| 1 | Camacho St. |
----------------------------------
tbl_reading_head
----------------------------------------------------------------------
| id_subscriber | id_soa_head | read_status | bill_month | bill_year |
----------------------------------------------------------------------
| 1 | NULL | Metered | 10 | 2017 |
----------------------------------------------------------------------
Notice that each id_subscriber has two (2) rows (one for electric, one for water). After grouping by id_subscriber:
GROUP BY rh.id_subscriber
I got this:
I tried adding COUNT before the sub-query making it:
COUNT(SELECT tbl_gen_info.gen_data_03 ...) AS group_area
but that doesn't work.
Use a subquery:
SELECT rh.group_area, COUNT(*)
FROM (SELECT rh.id_subscriber, rh.bill_month, rh.bill_year,
(SELECT tbl_gen_info.gen_data_03
FROM tbl_subscriber LEFT JOIN
tbl_gen_info
ON tbl_subscriber.bill_area_code = tbl_gen_info.gen_data_01
WHERE rh.id_subscriber = tbl_subscriber.id_subscriber
) as group_area
FROM tbl_reading_head rh
WHERE rh.id_soa_head IS NULL AND
rh.read_status <> 'Beginning' AND
rh.rec_status = 'active'
) rh
GROUP BY rh.group_area;

Selecting row with minimal value in one column, in a join query

I have two tables: tblBusinesses, tblBusinessImages that are matched on tblBusinesses.fldID = tblBusinessImages.fldBusinessID like this:
tblBusinesses
=============
fldID | fldName | fldTitle | fldBody
-------------------------------------
1 | b1 | title1 | body1
2 | b2 | title2 | body2
3 | b3 | title3 | body3
4 | b4 | title4 | body4
tblBusinessImages
=============
fldID | fldFileName | fldTitle | fldBusinessID | fldOrder
-----------------------------------------------------------
1 | img1.jpg | img1title | 1 | 3
2 | img2.jpg | img2title | 1 | 1
3 | img3.jpg | img3title | 1 | 2
I want to write a query that gets for every business in tblBusinesses, the image in tblBusinessImages with minimal fldOrder. In other words, in the example I wrote above I want to get business b1, title1, body1 along with img2.jpg from tblBusinessImages (because it has minimal fldOrder in tblBusinessImages ).
Any help would be appreciated!
If fldOrder alwyas starts at one for each fldBusinessID the query becomes
SELECT b.fldName, b.fldTitle, b.fldBody, i.fldFileName
FROM
tblBusinesses b
LEFT JOIN tblBusinessImages i
ON (b.fldID = i.fldBusinessID AND i.fldOrder = 1)
If not, you will have to use subqueries.
SELECT b.fldName, b.fldTitle, b.fldBody, firstImage.fldFileName
FROM
tblBusinesses b
LEFT JOIN (
SELECT i.fldBusinessID, i.fldFileName
FROM
tblBusinessImages i
WHERE
i.fldOrder = (SELECT MIN(x.fldOrder)
FROM tblBusinessImages x
WHERE x.fldBusinessID = i.fldBusinessID)
) firstImage
ON b.fldID = firstImage.fldBusinessID
Note that the left join makes the query return also businesses having no image at all.
If you need only entries having images where the smallest order id can have any value:
SELECT b.fldName, b.fldTitle, b.fldBody, i.fldFileName
FROM
tblBusinesses b
INNER JOIN tblBusinessImages i
ON b.fldID = i.fldBusinessID
WHERE
i.fldOrder = (SELECT MIN(x.fldOrder)
FROM tblBusinessImages x
WHERE x.fldBusinessID = i.fldBusinessID)
Do you only want to get the ONE entry with the smallest fldOrder?
Didn't test this query:
SELECT b.fldName,b.fldTitle,b.fldBody,bi.fldFileName,bi.fldOrder
FROM tblBuisnesses b
INNER JOIN tblBuisnessImages bi ON bi.fldBusinessID=b.fldID ORDER BY b.fldOrder DESC LIMIT 1;

how to update max row per group in SQL

I just added the 'default' column to my DB. I am trying to set the default value to '1' based on the latest 'addDate' per accountId.
+----+-----------+--------------------+--------+
| id | accountId | addDate | default|
+----+-----------+--------------------+--------+
| 1 | 45 |2012-02-29 08:41:59 | |
| 2 | 55 |2012-03-29 08:41:59 | |
| 3 | 45 |2012-04-29 08:41:59 | |
| 4 | 55 |2012-05-29 08:41:59 | |
| 5 | 60 |2012-05-29 08:41:59 | |
+----+-----------+--------------------+--------+
I found I was able to isolate the proper rows by using =>
select * from tble1
where addDate = (select max(addDate) from tble1 as sl where sl.accountId = tble1.accountId);
I need to be able to run an UPDATE that sets 'default' column to '1' only 1 time per 'accountId' basing it off of latest 'addDate'.
try this
UPdate Table1
SET `default` = 1
where addDate in (select * from (
select max(addDate) from table1 as sl group by accountId)t
)
DEMO HERE
UPDATE table1 x
LEFT
JOIN table1 y
ON y.accountid = x.accountid
AND y.adddate > x.adddate
SET x.default = 1
WHERE y.id IS NULL;
or (faster)
UPDATE table1 x
JOIN
( SELECT accountid
, MAX(addDate) max_adddate
FROM table1
GROUP
BY accountid
) y
ON y.accountId = x.accountId
AND y.max_adddate = x.adddate
SET x.default = 1;

i am not able to get data from three table geting error #1111 invalid use of group function

i have three tables
table A
------------------------------------------
filing_no | pet_name | res_name | court_no
------------------------------------------
1 | xyz | PQR | 1
------------------------------------------
2 | abc | def | 2
------------------------------------------
Table B
-------------------------------
filing_no |purpose_code|next_date
-----------------------------------
2 | 20 |3/8/2012
-----------------------------------
1 | 21 |3/9/2012
-----------------------------------
2 | 22 |3/10/2012
-----------------------------------
1 | 23 |15/11/2012
-----------------------------------
Table C.
-------------------------------------
purpose_code | purpose_name
-------------------------------------
20 | institution
-------------------------------------
21 | summon
-------------------------------------
22 | proceeding
-------------------------------------
23 | order
-------------------------------------
and i want result of particular court like:
--------------------------------------------------------
filing_no| Pet_name | res_name |purpose_name| next_date
--------------------------------------------------------
1 | xyz | PQR | Order | 15/11/2012
i execute the below query and got #1111 - Invalid use of group function ERROR.
please help.
select
a.filing_no as "File No", a.case_no as "Registration No", a.pet_name as Petitioner, a.res_name as Accused,
a.dt_of_filing as "Date of Inst",MAX(b.Next_date) as "Next Date",c.purpose_name as "Case Stage"
from filing_t a, Daily_proc b, Purpose_t c
where
a.filing_no = b.filing_no
and c.purpose_code = (
select purpose_code
from Daily_proc
where
filing_no = a.filing_no
and next_date = (
select MAX(next_date)
from Daily_proc
where filing_no = a.filing_no
)
)
and a.court_no = 1
and a.ci_cri = 2
and a.status = 'P'
group by b.filing_no
order by a.dt_of_filing DESC LIMIT 0 , 2000
You can only select the columns in GROUP BY and results from aggregate functions. For example what a.pet_name do you expect to be returned when there are different ones for the same b.filling_no?
answer Shared by #Devart i am very thankfull to him.
SELECT a.filing_no, a.pet_name, a.res_name, c.purpose_name, b.next_date FROM a
JOIN (SELECT * FROM (
SELECT * FROM b ORDER BY filing_no, next_date DESC
) t GROUP BY filing_no) b
ON a.filing_no = b.filing_no
JOIN c
ON b.purpose_code = c.purpose_code
WHERE a.court_no = 1;