Mysql get max row and min row from group of each row - php

I have MySQL table with employees attendance. first row of a day of employee treating as in time and last row of a day of employee treating as out time. I am trying to select first and last (min time and max time) from attendance table. It should give me two row sets. but my query not giving me as i expecting the result.
Table (Attendance)
My Query
select *, min(attdate) as intime, max(attdate) as outtime from attendance where empid=1
But above query not giving me as expected result. My output should be in below image. Please suggest me the query or give me hint to achieve given output.

this can be done by sub queries in where conditions.
SELECT * FROM attendance AS c WHERE empid=1 and (
attdate=( select min(attdate) from attendance where attendance.empid=c.empid )
or attdate=( select max(attdate) from attendance where attendance.empid=c.empid )
);

Unfortunately, MySQL doesn't offer window functions, so it's a bit more difficult here. You can use exists :
Select * from yourtable t
Where not exists (select 1 from yourtable s
Where t.empid = s.empid and
(s.attndate < t.attndate or s.attndate > t.attndate))
Though it seems you need to add another condition t.date = s.date unless you have only 1 day records stored there

Related

Get Last Payment From A User in SQL

I have this table
I am trying to get the sum of principal + interest from the last transaction date. Column 4. is the last transaction performed - [No column name] is the transaction date
What I have tried so far:
select sum(h.principal+h.interest) as amt_paid, MAX(h.trx_date)
from Loanhist h WHERE h.ac_no = '$id' and h.trx_type='LP'
GROUP BY principal, interest
The test data generation is for Oracle, but you should easily be able to adapt it. The actual query will work on SQL server. You'll need to use an approach like this if the account can post more than one transaction in a day. Otherwise the 'LIMIT/TOP 1' approaches in the other answers will work fine.
CREATE GLOBAL TEMPORARY TABLE balances
( ac_no CHAR(100),
principal FLOAT,
interest FLOAT,
tranDate DATE
)
ON COMMIT PRESERVE ROWS;
INSERT INTO balances VALUES (1,123.123,.456,DATE '2017-01-01');
INSERT INTO balances VALUES (1,100,.456,DATE '2017-01-02');
INSERT INTO balances VALUES (1,200,.1,DATE '2017-01-02');
INSERT INTO balances VALUES (2,200,.1,DATE '2017-01-02');
INSERT INTO balances VALUES (2,300,.1,DATE '2017-01-02');
SELECT SUM
( CASE WHEN tranDate = max_tran_date
THEN principal + interest
ELSE 0
END
) AS tranSum
FROM (SELECT sub.*,
MAX(tranDate) OVER() AS max_tran_date
FROM balances sub
) BAL;
Your question is not really clear. But if you just want to get the last transaction performed by the user, the best thing to do will be to rely on IDs instead of dates.
SELECT TOP 1 * FROM Loanhist h WHERE h.trx_type='LP' ORDER BY h.ac_no DESC
try to use LIMIT keyword.For Example, Select * from table name where condition LIMIT 1.It will return first row
Try this:
SELECT TOP 1 sum(h.principal+h.interest) as amt_paid, h.trx_date
FROM Loanhist h WHERE h.ac_no = '$id' AND h.trx_type='LP'
ORDER BY h.ac_no DESC;

Need help to make sql query to compare data column-wise

I have a mysql table which collects daily sales data (date, sale, gst etc). I need a select statement to compare daily sales for any given date with same date last year and year before, to see the how much we made on that day in previous years.
To give an idea of how the output table will look, I have an example table in jsfiddle.
And here is the sql table data in sqlfiddle.
I tried this statement:
SELECT * FROM sales_chc WHERE MONTH(sale_date) = '1'
It of course gives me the filtered results that I want but I couldn't figure out how to display the results in the give table example.
By changing year and month in the WHERE statement, you can get a report for whatever month/year combination you need.
SELECT sn.sale_date AS SaleY0 , sn.EFTPOS AS EFTPOSY0, sn.total AS totalY0,
s1.sale_date AS SaleY1 , s1.EFTPOS AS EFTPOSY1, s1.total AS totalY1,
s2.sale_date AS SaleY2 , s2.EFTPOS AS EFTPOSY2, s2.total AS totalY2
FROM sales_chc sn
LEFT JOIN sales_chc S1
ON s1.sale_date=(sn.sale_date -INTERVAL 1 YEAR)
LEFT JOIN sales_chc S2
ON s2.sale_date=(sn.sale_date -INTERVAL 2 YEAR)
WHERE YEAR(SN.sale_date)=2016 AND MONTH(SN.sale_date)=1
SQL fiddle

Order Mysql query by Name and other fields

I have a question about MySQL. I have a Table with this fields:
WorkerName
Date
HoursWorked
Ok, if I do this Query:
SELECT WorkerName, Date, HoursWorked, SUM(HoursWorked) FROM myTable GROUP BY WorkerName
I have the field grouped by the Worker Name BUT with a only row. I want to show all days worked by this Worker in the same row, and the other Worker in another row.
In PHP actually have a While that shows all days worked, but only shows the Hours of the first day sorted.
You can use GROUP_CONCAT aggregate function:
SELECT
WorkerName,
GROUP_CONCAT(Date) AS dates_worked,
SUM(HoursWorked)
FROM
myTable
GROUP BY
WorkerName

Join SQL query that has single id/row in 1 table, but links to multiple rows(same id) in another table?

First sorry for the long question title.
My question/situation is as such.
1.) I have 2 tables in mysql
2.) In first table, each listing has a unique id(each listing is in 1 row)
3.) In the second table it has the name/tags for images linked to the listing id,from the first table
4.) Each listing can have multiple images(multiple row in the second table).
What i am trying to do is to pull all the listings from table 1 and then use the listing.id from table one to pull all the rows of images from table 2 that are linked to the listing.id.
I am confused at the moment because there are multiple rows that has the same listing.id from table 2. ANd i tried query to display* but it only echo the last image(row) from table 2.
It doesnt seem to work when i join the 2 tables. And i am not sure if i query it twice then push array together.
Thanks for your time
$result=mysqli_query($con,"SELECT * FROM Listing JOIN listingpic ON
(Listing.id = listingpic.listingid)
WHERE date >= curdate() - INTERVAL DAYOFWEEK(curdate())+300 DAY GROUP BY Listing.id ORDER BY Listing.id DESC") or die( mysqli_error($con));
while ($row = mysqli_fetch_assoc($result))
{
$output[] = $row;
}
if (!empty($output)){
echo json_encode( $output );}
else{
echo json_encode( [] );
}
You only get one result per id, because you used GROUP BY Listing.id. If you do not group them, you get one result row for each table 2 row, including the Listing id each time.
If you wish to retrieve the data in one query in the form "one id: multiple data", you can use GROUP_CONCAT for example and then explode() the retrieved string result.
Otherwise get all ids from table 1 and then iterate over them in PHP and do one additional query per ID
Pro tip: Don't use the viciously confusing MySQL extension to GROUP BY. Read this: http://dev.mysql.com/doc/refman/5.6/en/group-by-handling.html
Pro tip: Don't use SELECT *, especially when you're joining tables. Instead, enumerate the columns you want in your result set.
Inherent to SQL is the idea that resultsets, like tables, are rectangular. They have rows and columns. Each row usually represents some real world item -- an "entity" -- and each column represents some attribute of that entity.
The result set you describe will, inherently, repeat information from your first table so it can show the info from the second table row by row.
What you want for a query is this, I think.
SELECT Listing.id, listing.date,
listingpic.id, listingpic.url, listingpic.caption
FROM Listing
JOIN listingpic ON Listing.id = listingpic.listingid
WHERE date >= curdate() - INTERVAL DAYOFWEEK(curdate())+300 DAY
ORDER BY Listing.id DESC, listingpic.id
This will give you one row per image.
If you're running out of memory it's because your result set is massive. You may want to limit it somehow, either using a first and last publication date:
WHERE date >= curdate() - INTERVAL DAYOFWEEK(curdate())+300 DAY
AND date < curdate() - INTERVAL DAYOFWEEK(curdate())+293 DAY
or with a LIMIT clause.
ORDER BY Listing.id DESC, listingpic.id
LIMIT 100

MySQL select between two dates not working as expected

I'm trying to create a query that will select all dates between two dates
This is my query:
$query = "SELECT DISTINCT * FROM D1,D2
WHERE D1.DATE_ADDED BETWEEN '$date1' AND '$date2' AND D1.D1_ID = D2.D2_ID";
The trouble is, it is not returning anything, but not producing an error either
So I tried inputting it directly into phpMyAdmin like this
SELECT DISTINCT * FROM D1,D2
WHERE D1.DATE_ADDED BETWEEN '2011-01-01' AND '2011-12-12'
AND D1.D1_ID = D2.D2_ID`
then like this
SELECT DISTINCT * FROM D1,D2
WHERE D1.DATE_ADDED BETWEEN '2011-01-01' AND '2011-12-12'
and like this
SELECT * FROM D1
WHERE DATE_ADDED BETWEEN '2011-01-01' AND '2011-12-12'
and I just get
MySQL returned an empty result set (i.e. zero rows). ( Query took 0.0003 sec )
Yes, my tables exist, and so do the columns :)
In the first cases the lack of results could be because of the inner join. For a result to be in the set it would require a record in both tables, ie. a record from d1 would not appear unless d2 also had that id in the d2_id column. To resolve this, if that is correct for your business logic, use left join.
However, the last of your cases (without the join) suggests the reasons is a lack of matching records in the first (left) table d1.
Without the full dataset we can't really comment further, since all the code you are running is perfectly valid.
If you always want to select an entire year it is easer to select it like this:
SELECT * FROM D1 WHERE YEAR(DATE_ADDED) = 2011;
Please implement below code
SELECT DISTINCT * FROM D1,D2
WHERE D1.DATE_ADDED BETWEEN DATE_FORMAT('2011-01-01','%Y-%m-%d')
AND DATE_FORMAT('2011-12-12','%Y-%m-%d')
AND D1.D1_ID = D2.D2_ID`

Categories