SQL query and for loops - mysql

I need a bit of help with a MySQL query. Right now I have a table that has 3 columns: location, street, and number. I want to write a query whose pseudocode would be...
for each location:
for each of the streets of a location
find the next biggest number
I feel like I am still thinking in "for-loop" logic, but that doesn't really seem to be the way MySQL operates, and it is tripping me up. Any help is greatly appreciated!
Also the primary key is the location-street combo

If I understand you right, you want the highest number of each street in each location?
SELECT
location,
street,
MAX(number)
FROM table
GROUP BY
location,
street
First of all, GROUP BY aggregates ("collapses") rows, so that only one row per location and street will be returned. In the list of rows to return, we then explicitly specify we want the highest number (MAX()) instead of the first one that would show up.
http://dev.mysql.com/doc/refman/5.6/en/group-by-handling.html
http://dev.mysql.com/doc/refman/5.6/en/example-maximum-column.html
http://dev.mysql.com/doc/refman/5.6/en/select.html
If it helps, you can think of a SELECT query (albeit very crudely) as filter rules for a loop that goes through every row of the entire table. In these "filter rules" you specify precisely what you want and how you want it, MySQL will then iterate over the entire table and handpick exactly the data you asked for.

Related

Getting the highest number from a mysql query

My issue is I need to create an order so I can move items up and down in this web application. However, I can not index the order(ord column) values by an index with an incremental value because there are several companies in the same table that use this column.
My table structure is this:
Right now I am thinking that the easiest way would be to do a MAX and grab the highest number and use that as an index in a way so you never end up with the same number twice for a specific companies listing when you go to add a new entry for a company.
SELECT MAX(ord) FROM phonebook WHERE `id_company` = "51";
Would this be a wise route to go? OR maybe create a new database for each client and create and index and use that as a way order entries?
I suggest you aim for less than complete perfection in your assignment of ord values. You can get away with this as follows:
don't make ord unique. (It isn't).
rely on the ordering of phonebook_name to get a good order of names. MySQL has these wonderful case-insensitive collations for precisely this purpose.
I suppose you're trying to make some of the entries for a company come first, and others come last. Set the ord column to 50 for everybody, then give the entries you want first lower numbers, and the ones you want last higher numbers.
When you display data for a particular company, do it like this ...
SELECT whatever, whatever
FROM phonebook
WHERE id_company = 11
ORDER BY ord, phonebook_name, phonebook_number, id_phonebook
This ORDER BY clause will do what you want, and it will be stable if there are duplicates. You can then, in your user interface, move an entry up with a query like this.
UPDATE phonebook SET ord=ord-1 WHERE id_phonebook = :recordnumber

Matching items in one table with their price in another table

So I have a Query with a list of "Items" Say 'APPLE', 'Carrot', and 'Pear', and a field beside it called "Quantity". On a another table I have a column with a field called "Item", then beside it a field with "cost". (Thus to show the item and its cost.) What I want to do is search the list for the item then take that item and times the price by the quantity, and show it on the chart.
Let's also assume that in the table of items that some of the spelling is not exact so one person may have typed apple and another apples, but in my item column it just says Apple, how do I make sure that they will find each other or the closest match on the list?
I have done a little work and I assume I have to create a join of some sort, but I am not sure of the expression to do the paring or the prices with the items once that is done a simple multiplication expression can be done.
You are right that you will need to perform a JOIN between the two tables/queries to match up the rows that correspond to each other ("apples to apples", so to speak). If your first table/query was called [Orders] and your second table/query was called [Prices] then a simple query to "do the math" would be something like
SELECT
Orders.Item,
Orders.Quantity,
Prices.Price,
Orders.Quantity * Prices.Price AS Cost
FROM
Orders
INNER JOIN
Prices
ON Orders.Item = Prices.Item
Regarding your point...
Lets also assume that in the table of items that some of the spelling
is not exact so one person may have typed apple and another apples,
but in my item column it just says Apple, how do I make sure that they
will find each other
...the short answer is: You design your database in such a way that such discrepancies cannot occur. Use your favorite Internet search engine to do some research on the following topics:
Data Validation
Referential Integrity
Edit re: comment
I was just wondering if I could use a Like function with % sign of some sort to search for the closest answer to solve the [matching] problem
Generally speaking, no. Those types of approaches can be very difficult to implement reliably (think "apples" vs. "pineapples") and can be very difficult to audit if incorrect matching occurs.
If you have dirty data then you're most likely just going to have to get busy and clean it up.

MySQL Query eliminate duplicates but only adjacent to each other

I have the following query..
SELECT Flights.flightno,
Flights.timestamp,
Flights.route
FROM Flights
WHERE Flights.adshex = '400662'
ORDER BY Flights.timestamp DESC
Which returns the following screenshot.
However I cannot use a simple group by as for example BCS6515 will appear a lot later in the list and I only want to "condense" the rows that are the same next to each other in this list.
An example of the output (note BCS6515 twice in this list as they were not adjacent in the first query)
Which is why a GROUP BY flightno will not work.
I don't think there's a good way to do so in SQL without a column to help you. At best, I'm thinking it would require a subquery that would be ugly and inefficient. You have two options that would probably end up with better performance.
One would be to code the logic yourself to prune the results. (Added:) This can be done with a procedure clause of a select statement, if you want to handle it on the database server side.
Another would be to either use other information in the table or add new information to the table for this purpose. Do you currently have something in your table that is a different value for each instance of a number of BCS6515 rows?
If not, and if I'm making correct assumptions about the data in your table, there will be only one flight with the same number per day, though the flight number is reused to denote a flight with the same start/end and times on other days. (e.g. the 10a.m. from NRT to DTW is the same flight number every day). If the timestamps were always the same day, then you could use DAY(timestamp) in the GROUP BY. However, that doesn't allow for overnight flights. Thus, you'll probably need something such as a departure date to group by to identify all the rows as belonging to the same physical flight.
GROUP BY does not work because 'timestamp' value is different for 2 BCS6515 records.
it will work only if:
SELECT Flights.flightno,
Flights.route
FROM Flights
WHERE Flights.adshex = '400662'
GROUP BY (Flights.flightno)

De-dupe a list of hundreds of thousands of first name/last name/address/date of birth

I have a large data set which I know contains many dupicate records. Basically I have data on first name, last name, different address components and date of birth.
I think the best way to do this is to use the name and date of birth as chances are if these things match, it's the same person. There are probably lots of instances where there are slight differences in spelling (like typos missing a single letter) or use of name (ie: some might have a middle initial in first name column) which would be good to account for, but I'm not sure how to approach this.
Are there any tools or articles on going about this process? The data is all in a MySQL database and I have a basic proficiency in SQL.
You could get a sense of how much dedupe you have to do by something like:
select birthDate,last_name,soundex(first_name),count(*)
from table
group by birthDate,last_name,soundex(first_name)
having count(*) >1
This will list the people with the same birthdate, last_name, and similar first names. Soundex() isn't great, but this could help you get a sense of amount of deduping.
This query below would allow you get the alphabetical first first_name from the table of similar named people. Hopefully this will give you some rough starting ideas//
select birthDate,last_name,soundex(first_name),min(first_name)
from table
group by birthDate,last_name,soundex(first_name)
having count(*) >1
With the second query, you could remove all occurrences of additional names, by using a DELETE where name not in, but that assumes you are willing to keep the lowest first_name and remove the rest...

Check this MySQL Query

This is my homework and the question is this:
List the average balance of customers by city and short zip code (the
first five digits of thezip code). Only include customers residing in
Washington State (‘WA’). also the Customer table has 5
columns(Name,Family,CustZip,CustCity,CustAVGBal)
I wrote the query like below. Is this correct?
SELECT CustCity,LEFT(CustZip,5) AS NewCustZip,CustAVGBal
FROM Customer
WHERE CustCity = 'WA'
No. Because you're truncating the zip code, you'll have many records that are duplicates. Your query needs to account for this and aggregate those into a single record. Also, you need a way to get the state from the zip code (are we missing another table). It's possible that you've omitted a column in your question -- if you have the state in the table, use it to select on.
No, that is not correct. You're asked to limit the people in the query by state, not city. To make the problem a little more interesting, there's no state column in the Customer table, so you're going to have to figure out how to limit the records without referring directly to the state.
Can you think of any ways to do this?
Your question isn't very clear "by city and short zip code". Depending on what that means exactly you might need to look at "group by" or "order by".
I think the assignment is expecting you to list a single average per city/short-code combination. You'll need to employ the GROUP BY clause and the AVG function.
Also, CustCity will never be 'WA'; you probably have to derive the 'WA' check from the zip code (I don't live in the U.S., but I guess that looking at the first two digits will suffice).
Your query isn't finding the average, it would return multiple rows for the same CustCity and NewCustZip. Look at the AVG function as well as the GROUP BY clause.
Also, the city's not going to be Washington. You probably need to get a list of all the zip-code prefixes for Washington and check for them in your query. Look here.
Yes Its Correct.