SQL - How to select/delete rows with the max value depending on two others - mysql

I'm an intern in a property rental company. I'm in charge of developping the CRM under Symfony.
So, ones of my entities are properties (houses) and their availabilities. See the table structure below.
The problem I'm facing for now, is that the availabilities had been defined for each day (e.g. 28/01, 29/01, 30/01) instead of being defined for a range of day (e.g. 28/01 -> 30/01). So, the table is really heavy (~710 000 rows). Furthermore, before we changed the way of editing an availability, it created a new row for a same date instead of editing it. So, there are a lot of duplications in this table.
What I want, is to lighten the DB by keeping only the rows which have the max value in date_modif_availabilities for the same date_availabilities and id_properties.
For example, if I have these rows (availabilities_duplications):
I only want to keep the row with the latest modif like this (availabilities_keep_max_value) :
The thing is, I don't know enough the SQL language. I'm able to write few basics scripts but not complex subqueries. Even with code samples that I found.
Thank you in advance for your help.

You could select the elements for which no element with greater modified date exists.
Something like this:
SELECT avl1.*
FROM availabilities avl1
WHERE NOT EXISTS (SELECT *
FROM availabilities avl2
WHERE avl1.date_availabilities = avl2.date_availabilities
AND avl1.id_properties = avl2.id_properties
AND avl2.date_modif_availabilities > avl1.date_modif_availabilities);
This of course has the pre-condition that the combination of the three columns date_availabilities, id_properties and date_modif_availabilities is unique.
Furthermore, it seems that all columns (except the PK) may be NULL. Looks kinda odd to me.

You can use subquery :
select t.*
from table t
where id_availabilities = (select t1.id_availabilities
from table t1
where t1.id_properties = t.id_properties and
t1.date_availabilities = t.date_availabilities
order by t1.date_modif_availabilities desc
limit 1
);
However, if you have concern about the performance, then you want index on (id_properties, date_availabilities and id_availabilities).

Related

SQL SUM condition on each column

I'm giving my best efforts to write a query to get the desired output format shown the second table here. Is there a better way to achieve this, table 1 has the raw data and I want to find the sum of monthly usage of unique devices for a given user. Any help is really appreciated.
table format
Apologize for not being clear in first place. tagged different image to illustrate better. If you look at this data in new image attached. After I filter by username - I get that data output. My need is to get the sum of usage by month by device.
Ex: rows highlighted in the image, where iPhone-6sPlus is used multiple times each month across months. I'm looking for a query that gives output as
iPhone-6SPlus is used xx_hrs in Jan, yy_hrs in feb so on. Similarly for other device models. Hope this helps. Thanks.
Better image
create table #product (model varchar(50),users varchar(5), monthofuse Varchar(3),yearofuse int,usage int)
Insert into #product values('X','a', 'JAN',2010,34), ('X','a', 'Feb',2010,20),('X','a', 'Mar',2010,10),('Y','a', 'Jan',2010,30),
('Y','b', 'Jan',2010,30),('Y','b', 'Feb',2010,30),('X','a', 'JAN',2011,50)
select * from #product
Select * FROM
(Select users,monthofuse,usage,model from #product) q
Pivot
(
sum(usage) for q.monthofuse in([JAN],[FEB],[MAR],[APR],[MAY],[JUN],[JUL],[AUG],[SEP],[OCT],[NOV],[DEC]))As pvttable

Tell from Which table MySQL COALESCE returned the value

i have the following part of query:
SUM(COALESCE(user_a, user_b)) AS income_adsense
Now, i have a html table in my web app where i present the data from this query.
problem is i want to mark data in one color if answer is from col user_a and different color if answer is from user_b col.
is there a way to achieve that in my query itself? (some sort of flag maybe?)
.
right now the only solution i have is to return all col's and work with the data on the client side but i am wondering if there's a cleaner/best practice solution.
guess it's worth mentioning i don't want to change the table structure.
Well, to make sense of the data I would do something like:
CASE
WHEN SUM(user_a) > SUM(user_b)
THEN 'User_A'
ELSE 'User_B'
END [Most of the data comes from]
You could also have two separate SUM() columns to make sense of this and compare the sum of values in your application.
SUM(user_a) [User_A Score Weight]
, SUM(user_b) [User_B Score Weight]

Mysql select part of field and return full value

Good day all,
I have a field called mCodes which has the exact length (7) throughout the table but with different values i.e. a few records with 5036100, 5036102, 5036103, 7010100, 7010101 etc.
I am using a select statement to first search for the first 4 characters i.e 5036 which will return all the records with 5036 just fine
I now need to return the actual full value of the records 5036100 etc. without recreating another sql statement. My statement I am using is as follow -
SELECT LEFT(MCODE, 4), MAKE, MODEL, NEWPRICE23 FROM mautogd1015 WHERE LEFT(MCODE, 4) = '5036'
I have racked my brain over this for a few hours now, any help will be appreciated.
Try something like this.
SELECT MCODE, MAKE, MODEL, NEWPRICE23 FROM mautogd1015 WHERE LEFT(MCODE, 4) = '5036'

MS Access Query using IFF to compare values

I am trying to build a query which will look at the data in two fields in two different tables and check to see if the data is the same, if it is I want it to return the number of times it is matched, if it isn't I simply want it to return the text saying "No viewings".
I have constructed this query in my access database which has the field from the first table "Property" and the second field I want it to compare the data with, "Viewings". I have build the following expression using the build tool, however I am stuck to make it work since every time I get this error message when trying to run the query: "Your query does not include the specified expression 'Property Viewed' as part of an aggregate function."
totalViewings: IIf([Viewings]![Property Viewed]=[Property]![ID],Count([Viewings]![Property Viewed]=[Property]![ID]),"No Viewings")
Any help how to overcome this error would be very appreciated.
Thanks
I would suggest doing something like this:
1) Assuming this is something you are developing yourself, make sure your data structure is all in order first. Since I dislike relatively code-hostile identifiers, I'd have the tables as so -
Properties - PropertyID (AutoNumber, primary key), HouseNumberOrName, Street, etc.
Viewings - ViewingID (AutoNumber, primary key), PropertyID (Number/Long Integer), ViewingDate, etc.
In the Relationships view, Properties.PropertyID would then be set up to point to Viewings.PropertyID in a one-to-many relation.
2) Your actual query I would then break into two, the first to compile the data and the second to format it for display. The first would go like this, saved as ViewingCounts...
SELECT Properties.PropertyID, Count(Viewings.PropertyID) As ViewingCount
FROM Properties LEFT JOIN Viewings ON Properties.PropertyID = Viewings.PropertyID
GROUP BY Properties.PropertyID;
... and the second like this, saved as ViewingCountsForDisplay:
SELECT Properties.*, IIf(ViewingCount = 0, 'No viewings', ViewingCount) AS Viewings
FROM Properties INNER JOIN ViewingCounts ON Properties.PropertyID = ViewingCounts.PropertyID
ORDER BY Properties.PropertyID;

MYSQL search table, bit fields

I have a table with rows and where one field is a bit-value with 7 digits.
Suppose I have a procedure where I want to select all rows where this bit field equals '0101010', this is easily done by select * where .... and so on.
But: how do I do if I want to allow one/multiple digits of the digits to be either 1 Or 0, i.e I want to get all rows where the bitfield has an entry on the form 1001*1* where the * can be either 1 or 0. So, in this case I would like all entries where the bit field is 1001010, 1001011, 1001110 or 1001111.
select * from TABLE where bit_field in (1001010, 1001011, 1001110, 1001111) would probably work in this example, but if I want to use only the string '1001*1*' as input to the procedure, what then?
.
Any help is very appreciated.
Thanks,
Niklas
Edit: I've tried this: select * from table where field like bit'\\\0'; for getting all entries of the form **0, but that didn't work...
Edit2: It turned out it vas a bit-field, not binary... problem still remain though.
Not a direct answer to your question, per se', but an alternative approach. You mentioned that you didn't want to convert to individual columns because of legacy code. If you do want individual columns and the only thing holding you back is the legacy code, consider the following.
You could add columns for the options and use insert/update triggers to populate them OR you could create a view that splits the bits into separate columns. For new development, you can code to the new columns. Over time, as you modify legacy code you can change it to the new approach. When all the "read" legacy code has been changed, the last step is to change the "write" code to use the new columns rather than the bit column and remove the triggers.
I have a SQL Fiddle demonstrating this here. Note that I only included an insert trigger for brevity.