MYSQL Select statement explanation - php

I have the following MYSQL select statement in a php file that was provided me by a programmer sometime ago.
I'm trying to make some edits to the file (I know enough PHP to "get myself into trouble").
Unfortunately, I don't understand this statement and what it means. I've never seen a select statement with "DOTS" in it (ie. a.weight or b.oil_type_id)
I don't understand howto read it. Here's the statement. Anyone know what this is supposed to mean?
$query11 = "SELECT avg(a.weight) as weight_avg
from oil_type a, oil_data b
where b.oil_type_id = a.oiltype_id
and b.viscosity_id = ". $viscosity_id_this;

It's the table alias. Notice in your query :
-- ...
FROM oil_type a
oil_type can now be referred to with the alias a. Therefore, when you see a.weight, it actually means oil_type.weight.
This is necessary in this case because there is a weight column in both tables you are selecting from. If you used only weight, MySQL wouldn't know which weight column to use, and would therefore return an error.
Edit: As Phil pointed in comments, there isn't necessarily two weight columns in this case, for some odd reason I thought you were joining your table with itself (therefore obviously duplicating the columns).

And even more - you can refer to it as database_name.table_name.column_name and have 2 dots in one name

You are qualifying the columns with their table names (or rather, their aliases):
SELECT avg( a.weight ) as weight_avg
FROM oil_type a, oil_data b -- b is an alias for oil_data, a is an alias for oil_type
-- also, there's an implicit join here
WHERE b.oil_type_id = a.oiltype_id
AND b.viscosity_id =". $viscosity_id_this;
This is necessary to remove ambiguity (ie: when a column with the same name exists in both tables). If the column names are not the same, you could use this for clarity.
The whole query could be rewritten as:
SELECT AVG(a.weight) as weight_avg
FROM oil_type AS a
INNER JOIN oil_data AS b
ON b.oil_type_id = a.oiltype_id
WHERE b.viscosity_id = $viscosity_id_this;
Which might be more clear (or not).

When selecting from multiple tables, the table name or its alias may be used, followed by a . and the column name in order to reduce/remove ambiguity between similarly named columns.
In this case, table oil_type is aliased as a and oil_data is aliased as b.

Related

SQL need help to group my results

Hey guy im looking to display some data from my oracle DB. im looking to group it by common data/column but cant figure it out.
$stid = oci_parse($conn, " SELECT REQ.REQSTN_NO, REQ.WO_NO, REQ.COST_CENTRE_CD, REQ.ACCT_PRIME_CD, REQ.ACCT_SUBSDRY_CD, REQ.STOCK_CD
FROM TE.REQSTNREQ
WHERE REQ.DEPT_CD='ISN'");
oci_execute($stid);
while (($row = oci_fetch_array($stid, OCI_BOTH+OCI_RETURN_NULLS)) != false) {
echo $row['COST_CENTRE_CD']."-".$row['ACCT_PRIME_CD']."-".$row['ACCT_SUBSDRY_CD']." ".$row['WO_NO']." ".$row['REQSTN_NO']." ".$row['STOCK_CD']."<br />";
}
Im looking to create an output like this
Ive tried Group BY and SUM/COUNT but i dont know how to structure the code properly any help would be appreciated.
This is not a real database "grouping" -- it is a display issue: you want to group rows with common column values together and print each shared column value only once.
Such display issues are best left to the presentation layer of your application and best left out of the SQL/data model layer.
Nevertheless, here is a technique you can use to group common column values together and to print each value only once, using SQL.
(Since you didn't provide your data in text form, this example uses DBA_OBJECTS to illustrate the technique).
SELECT
-- Order the row_number () partitions the same way the overall query is ordered...
case when row_number() over (partition by object_type order by object_type, owner, object_name) = 1 THEN object_type ELSE NULL END object_type,
case when row_number() over (partition by object_type, owner order by object_type, owner, object_name) = 1 THEN owner ELSE NULL END owner,
object_name,
created, last_ddl_time
FROM dba_objects o
ORDER BY
-- Important to qualify columns in ORDER BY...
o.object_type, o.owner, o.object_name;
The idea is that case statements check to see if this is the first row in a new shared common value and, only if so, to print the column value. Otherwise, it prints NULL.
You would need to use an object-relational database to achieve such a result.
Edited answer:
In MySQL you can use the following function: GROUP_CONCAT:
See reference: https://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html#function_group-concat
I believe there is a similar solution in oracle. You would need to refer to the following question:
Is there any function in oracle similar to group_concat in mysql?

SQL Update across 3 tables - Where clause issue(?)

We need to update various columns on 3 different tables via an input form. most of this is functional however when we try to update the other 2 tables that have been joined (publisher and category), it updates that record and every other record with the same input.
(for example if we change the genre from metal to jazz then all of the metal CD's will change to Jazz as well)
Below is the code we have so far for the update.
$sql = "UPDATE nmc_cd, nmc_category, nmc_publisher
SET CDTitle ='$title', CDYear = '$year', nmc_publisher.pubID = '$publisherID', nmc_category.catID = '$categoryID', CDPrice = '$price', pubName ='$pubName', catDesc='$catDesc'
WHERE CDID = $id
AND nmc_category.catID = nmc_cd.catID
AND nmc_publisher.pubID = nmc_cd.pubID";
I am relatively new to this site so please if anything such as code, names of variables/functions etc. is needed please say and I will edit my post or reply.
Thanks in advance!
A couple of recommendations.
1) qualify all column references in SQL statement that references more than one table, even when the column references aren't ambiguous to MySQL. (Also consider assigning a short alias to each table.) Several reasons for this, but one big one is that it lets a human reader know which table each referenced column is in.
2) ditch the old school comma operator for join operations, and use the JOIN keyword. Also move the join predicates from the WHERE clause to the appropriate ON clause.
3) for a multitable update, first write a SELECT statement, get that working and tested, and then convert that to an UPDATE statement
4) avoid SQL Injection vulnerabilities. The preferred pattern is to use prepared statements with bind placeholders. Or (less optimal) at a minimum, all potentially unsafe values that are included in the SQL text must be properly escaped.
Ignoring SQL Injection vulnerabilities (assuming that the contents of the variables have already been properly escaped)...
I would first write a SELECT statement that returns the current values of the columns we're planning to update, along with the new values we're planning to assign to those columns. For example:
SELECT cd.cdtitle AS old_cd_cdtitle
, '$title' AS new_cd_cdtitle
, cd.cdyear AS old_cdyear
, '$year' AS new_cdyear
, pub.pubid AS old_pub_pubid
, '$publisherID' AS new_pub_pubid
, cat.catid AS old_cat_catid
, '$categoryID' AS new_cat_catid
, cd.cdprice AS old_cd_cdprice
, '$price' AS new_cd_cdprice
, pub.pubName AS old_pub_pubname
, '$pubName' AS new_pub_pubname
, cat.catDesc AS old_cat_catdesc
, '$catDesc' AS new_cat_catdesc
FROM nmc_cd cd
JOIN nmc_category cat
ON cat.catID = cd.catid
JOIN nmc_publisher pub
ON pub.pubID = cd.pubid
WHERE cd.cdid = $id
(That is really just a guess, I'm not sure what you are actually trying to achieve.)
It seems really odd to assign a new value to the catid column, when that's referenced in a join predicate. To maintain the relationship between the rows in cd and cat, the catid in column in both tables would need to be updated, unless we're depending on an ON UPDATE CASCADE rule to propagate the change.
Without understanding what this statement is attempting to achieve, it's not possible to recommend any particular statement.
In terms of converting the SELECT into an UPDATE statement, replace the SELECT ... FROM with the keyword UPDATE.
And before the WHERE clause, add a SET statement. Taking the expresssions for old_cd_cdyear and new_cd_cdyear from the SELECT list, convert that into a SET clause like this:
SET cd.cdyear = '$year'
Subsequent assignments, use a comma in place of the SET keyword, e.g.
, cd.cdprice = '$price'

Can't understand this MySQL Query Purpose

I'm doing an internship as Web Developer, I'm a bit new and i'm here to ask your experience to clarify my doubts; while i was working on a website that someone else made i found this query:
$query = "SELECT a.upload_date, a.zipfile, a.lang, b.*
FROM something_uploadform as a , something2_stayinformed as b
WHERE a.uid_head =b.uid and a.zipfile<>'' order by ".$orderby." desc";
Can anyone help me to understand it? I thought that this piece of code picks a record and attach it to an a, isn't it?
Thanks everyone.
At a high level, this query is doing an implicit JOIN on two tables. Let's break it down:
The data is coming from two tables (AS gives the table an alias):
something_uploadform as "a" (this table will now be known as a)
something2_stayinformed as "b" (this table will now be known as b)
The columns being selected:
a.upload_date
a.zipfile
a.lang
b.* (All columns in table b)
The tables are being joined on the columns:
a.uid_head = b.uid
The filter being applied:
a.zipfile <> '' (where the column zipfile is not empty)
The sort being applied:
$orderby DESC (passed variable, sorted in descending order)
something_uploadform as a defines a as an alias for something_uploadform so you don't have to specify the full table name when selecting columns.

How can I use the AND statement to compare two tables?

I'm trying to write a statement that will check 2 tables and compare the 2 and only show the users who are not on table2. For example:
table1 has user1, user2, user3, and user4 AND
table2 has user1, user3, and user4 then it would only show user2 in the list.
I was able to write something as basic as to only show member_id='1' but I don't how to make it work the way I would like. I'm hoping you understand my question. I'll include the short code that deals with this issue...
$sql->db_Select(DB_TABLE_ROSTER_MEMBERS, "*", "member_id='1' AND
(member_status like 'Team Member%'
OR member_status like 'Squad Leader%'
OR member_status like 'Recruiter%'
OR member_status like 'New Recruit%'$customArgs)
ORDER BY member_application_date DESC");
the syntax for this can be located here- http://wiki.e107.org/index.php?title=Db#db_Select.28.29
I'm guessing I just need to make another select DB and just have it included in the above so it would be something like
member_id != $member_id
where $member_id would be something like $member_id = $row['member_id'];
You need to make a LEFT JOIN and check where table2.member_id IS NULL.
First, AND is an operator ;)
Second, there are many relational operators that imply logical AND e.g. intersect, join, product (SQL CROSS JOIN), restriction (SQL WHERE, extension (SQL AS clause) and matching/difference (SQL MATCH or EXISTS or IN).
Third, from your first sentence I rather think you are looking for relational operators that imply logical NOT i.e. non-existential qualification. Again, there are many options e.g. minus (SQL EXCEPT), not matching/semi-difference (SQL NOT EXISTS or NOT IN but bizarrely not NOT MATCH!); personally, I find OUTER JOIN testing for nulls to be the most odd (not to mention not relational)!
Fourth, your relational/SQL product of choice will likely not support and/or equally optimize all the different options from a given relational algebra or SQL Standard.
My personal choice for semi-difference is NOT EXISTS: the name clearly implies non-existential qualification, the predicates are located close together in SQL code, is widely supported and usually well optimized:
SELECT *
FROM table1
WHERE NOT EXISTS (
SELECT *
FROM table2
WHERE table2.member_id = table1.member_id -- predicates close together
);

How to set the relative order of columns with a zfdatagrid?

To those of you who are familiar with zfdatagrid for the Zend framework:
I got a recordset by a JOIN query, say from tables s and t, now I want to set the order in which the columns appear in the deployed table.
For example,
5th column of table t to appear at the leftmost side,
then 3rd column of table s,
then 2nd column of table t,
then 4th column of table s.
How do I do this? Whatever I tried, it always shows first the columns of the left table of the JOIN, then the columns of the right table of the JOIN.
I only know how to tell it which columns to show, but not their order.
It may be late but may be useful for others
You can use:
$grid->updateColumn($field,array('position'=>$i))

Categories