I have 2 tables
Table1
ID . Name . Position
= = = = = = = = = = = =
10 . Mike . Analyst
20 . Anna . HR
30 . Mark . Accountant
Table2
Deal ID . Status
= = = = = = = = = = = =
10 . . . . . Active
19 . . . . . New
20 . . . . . New
I want to add a new Calculated Column in Table1 with this logic :
If ID found in Table2 then return Position, ELSE return "NONE"
so the output table should be like this
Outout
ID . Name . Position . . . . **NewCol**
= = = = = = = = = = = = = = = = =
10 . Mike . Analyst . . . . . **Analyst**
20 . Anna . HR . . . . . . . . **HR**
30 . Mark . Accountant. . **NONE**
There are two ways to accomplish that.
Query Based Result
If you just want to display the information every time you need it, the simplest, cleanest and efficient way is just to perform a SELECT within the tables. In addition, the data will allways be updated, because the query runs over the actual table state.
So, the query would look like this:
SELECT T1.*, IF(T2.ID IS NULL, 'NONE', T1.Position) As NewPos
FROM Table1 T1 LEFT OUTER JOIN Table2 T2
ON (T1.ID = T2.ID)
This query will show the position if found on Table2 and, if not, it will display NULL value, so it may be useful for your needs.
Database Modification and Data Inserting
The other way, is to alter the Table1 structure to add the column Position. The existence of the column is referred to the table architecture, it is not value dependant, so you can't alter a Table and adding the column based on row values.
So, the first step to do is to alter the table adding the column, something like this:
ALTER TABLE table1 ADD COLUMN Position VARCHAR(50);
The second step is to fill the data. For this, you will have to perform an UPDATE to fill the data you have just created, something like this.
UPDATE Table1 T1 LEFT OUTER JOIN Table2 T2
ON (T1.ID = T2.ID)
SET T1.Position = IF(T2.ID IS NULL, 'NONE', T1.Position);
This query will update the rows which also exists in Table2 referenced by ID and will put its position.
The problem of this way it's that if you perform this and after, you add rows to Table1 and Table2, the information will not be updated and you'll have to do the UPDATE query every certain time, which is database and time cost.
So, if the application is not too big, in this case is better to use just the SELECT query, which involves less cost, performance and database changes.
Related
I need to translate this query which works in SQL Server to MySQL. I've circled around it at least 50 times and am stumped and cannot even find a starting point.
The issues in a nutshell:
It has not one but two FULL OUTER joins which MySQL does not do. I
know this can be emulated some how using UNION in combination with LEFT and RIGHT joins.
It joins the tables on multiple conditions and I am not sure how to add exclusion
criteria in the ON if doing a typical RIGHT JOIN
SELECT COALESCE(ca.reporting_period, s_p.reporting_period, s_uy.reporting_period) AS reporting_period,
COALESCE(ca.state, s_p.state, s_uy.state) AS state,
COALESCE(ca.servicer, s_p.servicer, s_uy.servicer) AS servicer,
COALESCE(ca.product, s_p.product, s_uy.product) AS product,
COALESCE(ca.product_group, s_p.product_group, s_uy.product_group) AS product_group,
COALESCE(ca.portfolio, s_p.portfolio, s_uy.portfolio) AS portfolio,
COALESCE(ca.channel, s_p.channel, s_uy.channel) AS channel,
ca.Gross,
ca.Costs,
ca.commission,
ca.commissionable,
s_p.WAVG_placed_numerator,
s_p.place_balance AS WAVG_placed_denominator,
SUM(s_uy.cum_gross) AS gross_uy_num,
SUM(s_uy.cum_netnet) AS netnet_uy_num,
SUM(s_uy.cum_commission) AS servicer_uy_num,
SUM(s_uy.num_accounts) AS uy_den,
ca.costs_recovered
# INTO adhoc_work.RevenueReport_Legal
FROM adhoc_work.Cash ca
FULL OUTER JOIN adhoc_work.Summary_placed s_p
ON ca.reporting_period = s_p.reporting_period
AND ca.state = s_p.state
AND ca.servicer = s_p.servicer
AND ca.product = s_p.product
AND ca.product_group = s_p.product_group
AND ca.portfolio = s_p.portfolio
AND ca.channel = s_p.channel
FULL OUTER JOIN adhoc_work.Summary_uy s_uy
ON ca.reporting_period = s_uy.reporting_period
AND ca.state = s_uy.state
AND s_p.state = s_uy.state
AND ca.servicer = s_uy.servicer
AND s_p.servicer = s_uy.servicer
AND ca.product = s_uy.product
AND s_p.product = s_uy.product
AND ca.product_group = s_uy.product_group
AND s_p.product_group = s_uy.product_group
AND ca.portfolio = s_uy.portfolio
AND s_p.portfolio = s_uy.portfolio
AND ca.channel = s_uy.channel
AND s_p.channel = s_uy.channel
WHERE COALESCE(ca.reporting_period,s_p.reporting_period,s_uy.reporting_period) BETWEEN DATE_FORMAT(TIMESTAMPADD(MONTH,-13,NOW(3)),'%Y%m%d') AND DATE_FORMAT(NOW(3),'%Y%m%d')
GROUP BY COALESCE(ca.reporting_period,s_p.reporting_period,s_uy.reporting_period)
,COALESCE(ca.state,s_p.state,s_uy.state)
,COALESCE(ca.servicer,s_p.servicer,s_uy.servicer)
,COALESCE(ca.product,s_p.product,s_uy.product)
,COALESCE(ca.product_group,s_p.product_group,s_uy.product_group)
,COALESCE(ca.portfolio,s_p.portfolio,s_uy.portfolio)
,COALESCE(ca.channel,s_p.channel,s_uy.channel)
,ca.gross
,ca.Costs
,ca.commission
,ca.commissionable
,s_p.WAVG_placed_numerator
,s_p.place_balance
,ca.costs_recovered;
Actually, your query doesn't quite do a full outer join, because a condition like this:
ca.state = s_uy.state
requires that ca.state be matched. That is, the outer join is turned to an inner join.
So, to answer your question more theoretically, the simplest method is probably to generate all the rows by using UNION among the the table and then use left join:
FROM (SELECT reporting_period, . . .
FROM adhoc_work.Cash ca
UNION -- on purpose to remove duplicates
SELECT reporting_period, . . .
FROM adhoc_work.Summary_placed
UNION -- on purpose to remove duplicates
SELECT reporting_period, . . .
FROM adhoc_work.Summary_uy
) x LEFT JOIN
adhoc_work.Cash ca
ON x.reporting_period = ca.reporting_period AND
. . . LEFT JOIN
adhoc_work.Summary_placed s_p
ON x.reporting_period = s_p.reporting_period AND
. . . LEFT JOIN
adhoc_work.Summary_uy s_uy
ON x.reporting_period = s_uy.reporting_period AND
. . .
I'm new to MySQL and I'm trying to make the following pseudocode work:
SELECT IF(
EXISTS(SELECT * FROM users WHERE `email`="admin" AND `token`="blablabla"),
(UPDATE * FROM sometable WHERE `var`="notimportant"),
"NOT_AUTHORIZED");
What I'm trying to achieve is running code based on the presence of a row, and if it doesn't exists return a message, or something usable. If it does exists, run another SQL command instead, and return those results.
Is this possible?
Your intent is a bit hard to follow from the invalid syntax. But the gist of your question is that you can use a where clause:
UPDATE sometable
SET . . .
WHERE var = 'notimportant' AND
EXISTS (SELECT 1 FROM users WHERE email = 'admin' AND token = 'blablabla');
You can also represent this as a JOIN. Assuming the subquery returns at most one row:
UPDATE sometable t CROSS JOIN
(SELECT 1
FROM users
WHERE email = 'admin' AND token = 'blablabla'
LIMIT 1
) x
SET . . .
WHERE var = 'notimportant' ;
Basically I do while two time to get main group & group value. Example
$group_query = $db->query("
SELECT opt_id, opt_type
FROM ads_options
WHERE opt_id = '" . intval($data['ad_id']) . "'
GROUP BY opt_type");
while ($group_data = $db->fetch($group_query)) {
$option_query = $db->query("
SELECT *
FROM ads_options
WHERE opt_id = '" . intval($data['ad_id']) . "'
AND opt_type ='" . $group_data['opt_type'] . "'
ORDER BY opt_id DESC");
while ($option_data = $db->fetch($option_query)) {
}
}
Output :
Size : S
M
L
Color : White
Black
Question :
How to join current queries above with single statement?
Update :
Current database structure
opt_id opt_type opt_name opt_price
1236 Size S 0
1236 Size M 1
1236 Color Black 1
1236 Color White 2
Something like this would get the unique combinations, may be of help
$group_query = $db->query("
SELECT
DISTINCT opt_id, opt_type, opt_size
FROM ads_options
WHERE opt_id = " . intval($data['ad_id']) . "
ORDER BY opt_type, opt_size");
If you are able to supply more details as to precisely what you are trying to achieve, and the full design of ads_options, then it would be easier to provide more specific advice
Also a minor note, if opt_id is numeric then you don't need single quotes (') around it within the query (so removed them in example)
EDIT
Something like the following would return you a list of id, type, and then as third field a comma-delimited list of values, if that's of more help
$group_query = $db->query("
SELECT
opt_id, opt_type, GROUP_CONCAT(opt_name) AS opt_names
FROM ads_options
WHERE opt_id = " . intval($data['ad_id']) . "
ORDER BY opt_type");
For more information on GROUP_CONCAT check out this link http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
I've no idea if PHP programatically has something to help with this, I tend to use Coldfusion so if anyone knows of a PHP version of doing the following then that seems to match what OP was asking for
<cfoutput query="qryAdOptions" group="opt_type">
#qryAdOptions.opt_type#
<cfoutput>
#qryAdOptions.opt_name#
</cfoutput>
</cfoutput>
http://bytes.com/topic/php/answers/11929-grouping-results-query#post50606 seems to suggest the following as potentially a match for the I posted above so may be useful
$answer = array();
while ($row = pg_fetch_array($results)) {
if (!isset($answer[$row["obj_type"]])) {
$answer[$row["obj_type"]] = array();
}
$answer[$row["obj_type"]][] = $row;
}
You then iterate over $answer. This would play nicely with
SELECT * FROM ads_options WHERE opt_id = ......
Here is how the the database is layout. I can connect to DB fine.
I had it pullling from database two things but adding a third i can not get it to pull. I just need some help if i could ..
database - mmoore_drupal
table 1
table name = content_type_uprofile
data
vid= 19723
nid =19674
field_name_value = matthew moore
table 2
table name = location_instance
data
lid = 1521
vid = 19723
nid = 19674
table 3
table name = location
data
lid = 1521
street =
city =
country =
latitude =
longitude =
I am trying to pull name and then other info from the other two tables. But mainly i need to have name and other information from location. I thought i had to have the other table to associate the connection. Any help is appreciated.
$query = "SELECT content_type_uprofile.field_name_value,location.street,location.city
FROM location_instance,location,content_type_uprofile
WHERE location_instance.lid = location.lid and location_instance.nid=content_type_uprofile.nid"
$result = mysql_query($query) or die(mysql_error());
// Print out the contents of each row into a table
while($row = mysql_fetch_array($result)){
echo $row['nid']."-".$row['street']. " - ". $row['city'];
echo "<br />";
}
?>
Use this SQL (explicit join syntax):
SELECT
content_type_uprofile.nid,
location.street,
location.city
FROM
content_type_uprofile
INNER JOIN location_instance
ON (content_type_uprofile.nid = location_instance.nid)
INNER JOIN location
ON (location_instance.lid = location.lid)
The SQL that you posted is using implicit join SQL syntax.
I think for some reason, I think the line in your SQL:
WHERE location_instance.lid = location.lid and location_instance.nid=content_type_uprofile.nid
is filtering out all the rows from your result set. I'm not sure because I avoid the implicit syntax.
You were also missing the nid field which your PHP code is looking for in the result set.
As long as your data is correct (i.e. the fields that you are joining on have the right values), the SQL that I posted will work for you.
You ever done something with join's?
select *.locaition,
*.content_type_uprofile
from location_instance li
inner join location l on l.lid = li.lid
inner join content_type_uprofile ctu on ctu.vid = li.vid
What is the correct way of retrieving maximum values of all columns in a table with a single query? Thanks.
Clarification: the same query should work on any table, i.e. the column names are not to be hard-coded into it.
SELECT max(col1) as max_col1, max(col2) as max_col2 FROM `table`;
I think (but would be happy to be shown wrong) that you have to know at least the number of columns in the table, but then you can do:
select max(c1),max(c2),max(c3),max(c4),max(c5)
from (
select 1 c1, 1 c2, 1 c3, 1 c4, 1 c5 from dual where 0
union all
select * from arbitrary5columntable
) foo;
Obviously you lose any benefits of indexing.
You're going to have to do it in two steps - one to retrieve the structure of the table, followed by a second step to retrieve the max values for each
In php:
$table = "aTableName";
$columnsResult = mysql_query("SHOW COLUMNS FROM $table");
$maxValsSelect = "";
while ($aColumn = mysql_fetch_assoc($columnsResult)) {
if (strlen($maxValsSelect) > 0) {
//Seperator
$maxValsSelect .= ", ";
}
$maxValsSelect .= "MAX(" . $aColumn['Field'] . ") AS '" . $aColumn['Field'] . "'";
}
//Complete the query
$maxValsQuery = "SELECT $maxValsSelect FROM $table";
$maxValsResult = mysql_query($maxValsQuery);
//process the results....