My problem is:
I have a dbase query (A) with events_A with today date
$STH_1 = $DBH_R->query("SELECT table_name
FROM information_schema.tables
WHERE table_name
LIKE 'v_c_ei\_9%' ");
$stmts_1 = array();
while (($row_1 = $STH_1 -> fetch_assoc()) !== null){
$table_name = $row_1['table_name'];
$stmts_1[] = sprintf("
SELECT *
FROM $table_name
WHERE date_time = $today_date
");
}
$stmt_1 = implode("\nUNION\n", $stmts_1);
$stmt_1 .= "\nORDER BY date_time ASC";
$STH_5_2 = $DBH_R->query($stmt_1);
while (($row_5_2 = $STH_5_2 -> fetch_assoc()) !== null) { }
and I can display the results from this in the table_A.
But I have a dbase query (B) with events_B with today date
$table_name_2 = 'v_c_e';
$STH_e = $DBH_R->query("
SELECT *
FROM `$table_name_2`
WHERE date_time = $today_date
");
while (($row_e = $STH_e -> fetch_assoc()) !== null) { }
and I can display the results from this in the table_B.
The source tables for the first query and for the second query have only one common column - date_time.
What I must to do (and how) to display events_A and events_B in one table (ORDER BY date_time ASC)? - and for future - how add events_C (f.ex. similar to events_B)?
// I know that after all I need to format the data so that they look similar and it can be displayed in one table.
I'm not clear from your question whether you want to join the results - that is, the information from both tables is related in that two records sharing a date_time should be the same event - or unrelated.
If it is the latter, you cannot combine them meaningfully; you effectively have two different schemas.
If the information in tables A and B refers to the same events, and the date_time is a unique key, then you can do the following:
SELECT * FROM events_A, events_B WHERE events_A.date_time=events_B.date_time;
... or the like.
I think, from the query you built in PHP, you're not very strong on the features of SQL and when you would want to use them. It might be worth reading something like this guide to get a better handle on what should be done in the database rather than in PHP code before proceeding.
Related
This is 4 queries put into one. This is really old code and once I can make this work we can update it later to PDO for security. What I am trying to do is count rows from
select count(*) from dialogue_employees d_e,
dialogue_leaders d_l where
d_l.leader_group_id = d_e.leader_group_id
and use it in a formula where I also count how many rows from dialogue.status = 1.
The formula is on the bottom to create a percentage total from the results. This is PHP and MySQL and I wasn't sure the best way to count the rows and put them as a variable in php to be used in the formula on the bottom?
function calculate_site_score($start_date, $end_date, $status){
while($rows=mysql_fetch_array($sqls)){
$query = "
SELECT
dialogue.cycle_id,
$completecount = sum(dialogue.status) AS calculation,
$total_employees = count(dialogue_employees AND dialogue_leaders), dialogue_list.*,
FROM dialogue,
(SELECT * FROM dialogue_list WHERE status =1) AS status,
dialogue_employees d_e,
u.fname, u.lname, d_e.*
user u,
dialogue_list,
dialogue_leaders d_l
LEFT JOIN dialogue_list d_list
ON d_e.employee_id = d_list.employee_id,
WHERE
d_l.leader_group_id = d_e.leader_group_id
AND d_l.cycle_id = dialogue.cycle_id
AND u.userID = d_e.employee_id
AND dialogue_list.employee_id
AND site_id='$_SESSION[siteID]'
AND start_date >= '$start_date'
AND start_date <= '$end_date'";
$sqls=mysql_query($query) or die(mysql_error());
}
$sitescore=($completecount/$total_employees)*100;
return round($sitescore,2);
}
If you separate out your queries you will gain more control over your data. You have to be careful what your counting. It's pretty crowded in there.
If you just wanted to clean up your function you can stack your queries like this so they make more sense, that function is very crowded.
function calculate_site_score($start_date, $end_date, $status){
$query="select * from dialogue;";
if ($result = $mysqli->query($query))) {
//iterate your result
$neededElem = $result['elem'];
$query="select * from dialogue_list where status =1 and otherElem = " . $neededElem . ";";
//give it a name other than $sqls, something that makes sense.
$list = $mysqli->query($query);
//iterate list, and parse results for what you need
foreach($list as $k => $v){
//go a level deeper, or calculate, rinse and repeat
}
}
Then do your counts separately.
So it would help if you separate queries each on their own.
Here is a count example How do I count columns of a table
I have 4 tables
Tbl_Items:
Asset Id,
Asset_name,
Workshop,
PAT_PASS
(workshop, and PAT_PASS are either YES or NO. Workshop = YES and PAT_PASS = NO means this item is not available for hire..)
Tbl_Project_details:
Project_id,
Project_start_date,
project_end_date
TBL_Project_items:
Project_id,
Asset_id,
Start_date,
End_date
I need to do a select statement that allows me to show all the items in tbl_Items EXCEPT:
1) Those that are already in use on another project on the dates that I need them.
2) Are in the workshop. (Workshop = YES)
3) Are not PAT Tested (PAT_PASS = NO)
So far I have started with a simple statement like this:
$post_project_id = "13-1309.01"; //this is just an example number..
$sql =
"SELECT * FROM Project_details
Where Project_id = '$post_project_id' ";
$result = mysql_query($sql);
while ($row = mysql_fetch_array($result))
{
$hire_start_date = $row['Start_date']; // we find out our projects start date
$hire_end_date = $row['End_date']; // we find out our projects end date
}
$result=mysql_query("SELECT Items.Asset_id, Items.Name
FROM
Items,Project_items
WHERE
Project_details.Start_date < '$hire_start_date'
AND
Project_details.End_date > '$hire_end_date'")
or die(mysql_error());
while($row = mysql_fetch_array($result))
{
// fill up an option box with the results
}
Even this basic script doesn't seem to work! This is the first time I have tried selecting from multiple tables, so this is a steep learning curve!
Thanks!
I would go with a subquery:
SELECT * FROM Tbl_Items AS i WHERE
this should matches your (1.) condition: "take only those records, which with that select dont have any occurences":
0 = (
SELECT COUNT(1) FROM TBL_Project_items AS pi
WHERE i.Asset_Id = pi.Asset_Id
AND Start_date < $hire_start_date
AND End_date > $hire_end_date
)
workshop condition (2.):
AND WORKSHOP != "YES"
pat tested condition (3):
AND PAT_PASS != "NO"
$StartDate and $EndDate are your date constraints:
SELECT ITEM.asset_id,
ITEM.asset_name,
ITEM.workshop,
ITEM.pat_pass
FROM Tbl_Items ITEM
LEFT JOIN Tbl_Project_Items PJITEM
ON PJITEM.asset_id = ITEM.asset_id
AND PJITEM.start_date BETWEEN $StartDate AND $EndDate
OR PJITEM.end_date BETWEEN $StartDate AND $EndDate
WHERE ITEM.workshop = 'no'
AND ITEM.pat_pass = 'yes'
AND PJITEM.asset_id IS NULL
Who's Pat?
One problem:
WHERE
Project_details.Start_date < '$hire_start_date'
AND
Project_details.End_date > '$hire_end_date'")
The columns "Start_date" and "End_date" aren't in the "Project_details" table. In that table, those columns seem to be named "Project_start_date" and "Project_end_date".
Hello I would like to query multiple identical tables in my db which has different prefixes and than display the results randomly but somehow I need to track the origin of the item and I couldn't figure out how
I do the query like this because I don't have access to information_schema
$query = "SHOW TABLES FROM mydb WHERE RIGHT( tables_in_mydb, 5 ) = 'table'";
$res = mysql_query($query);
$num = mysql_num_rows($res);
while($row = mysql_fetch_row($res)) {
$numbers = explode('_', $row[0]);
if($num > 0) {
$q = "SELECT `this`, `that`, `something` FROM ".$numbers[0]."_idetinticaltables"; // :)
$r = mysql_query($q);
while($c = mysql_fetch_array($r)) {
/*display the results randomly with an identifier where the come from*/
}
}
}
You could use ORDER BY RAND() to randomly sort it
The following might work:
Get the list of the tables you're interested in. You already do that.
Create a UNION of multiple SELECT statements. Each SELECT statement differs for the table being selected from and you add a column set to the name of the table (so you can identify it later):
(SELECT *, TABLENAME = 'first_name_of_table' FROM first_name_of_table ...)
UNION
(SELECT *, TABLENAME = 'second_name_of_table' FROM second_name_of_table ...)
UNION
...
ORDER BY RAND() LIMIT 10;
Because it is a UNION you can randomize the whole order then. See How can i optimize MySQL's ORDER BY RAND() function? because it is not that trivial to do well, the example above is only to have an ORDER BY and LIMIT clause placed there. With many entries in your tables, it will kill your server.
$aa=array()
while($c = mysql_fetch_array($r))
{
/*display the results randomly with an identifier where the come from*/
$aa[]=$c;
}
echo $aa; // print "Array"
$STH_1 = $DBH_R->query("SELECT table_name
FROM information_schema.tables
WHERE table_name
LIKE 'v_c_ei\_9%'
");
$stmts_1 = array();
while (($row_1 = $STH_1 -> fetch_assoc()) !== null){
$table_name = $row_1['table_name'];
$stmts_1[] = sprintf("SELECT *
FROM $table_name
WHERE (ei_code = '1117') AND (DAY(date_time) != '00')
");
}
$stmt_1 = implode("\nUNION\n", $stmts_1);
$stmt_1 .= "\nORDER BY date_time ASC";
$STH_5_2 = $DBH_R->query($stmt_1);
while (($row_5_2 = $STH_5_2 -> fetch_assoc()) !== null){
OK, the script above is working ok. But, I want (must) change its functionality. I must do selection before UNION (something like ORDER BY ... LIMIT) but I know - this is not working. The solution is to change sprintif into UNION & UNION & UNION ... But the problem is - we don't know how much tables we have.
The table names from the first query looks like
v_c_ei_9001
v_c_ei_9002
..........
v_c_ei_9030
..........
ect.
Than the q: how change the sprintif (and maybe array $stmts_1 too) from abowe into the UNION in situation when we don't know how much tables we have?
thnks
When you add ORDER BY and LIMIT clauses to each constituent of the UNION, as follows:
while (($row_1 = $STH_1 -> fetch_assoc()) !== null){
$table_name = $row_1['table_name'];
$stmts_1[] = sprintf("SELECT *
FROM $table_name
WHERE (ei_code = '1117') AND (DAY(date_time) != '00')
ORDER BY date_time DESC LIMIT 1
");
}
And then you do the following:
$stmt_1 = implode("\nUNION\n", $stmts_1);
$stmt_1 .= "\nORDER BY date_time ASC"; // <---- remember this bit
The resulting string in $stmt_1 will look something like this:
SELECT *
FROM v_c_ei_9001
WHERE (ei_code = '1117') AND (DAY(date_time) != '00')
ORDER BY date_time DESC LIMIT 1
UNION
...
UNION
SELECT *
FROM v_c_ei_9030
WHERE (ei_code = '1117') AND (DAY(date_time) != '00')
ORDER BY date_time DESC LIMIT 1
ORDER BY date_time ASC -- it's appearing down here!
As you can see, the final constituent of your UNION has two ORDER BY clauses, which is a syntax error. Either remove the line commented remember this bit above, or else (if you need to reorder the unified queries) you must make the UNION a subquery to an outer query that performs the reordering:
$stmt_1 = "SELECT * FROM ("
$stmt_1 = implode("\nUNION\n", $stmts_1);
$stmt_1 .= ") ORDER BY date_time ASC";
As I see, the simple way to show itself is write whatever, instead consider the solution of the problem. The situation is similar to evaluating questions - if the complexity of the problem is beyond the involvement of the viewer it is easier to evaluate them negatively than actually help the man who asks. And not just speak, instead of writing anything.
For all those who may face such a problem I give operating solution.
The simplest overall solution was to specify the tables on which the main query is executed. What was to be obtained in the main query by ORDER BY was obtained first auxiliary request on the first query by pre-rank the tables on the main query is executed.
In this way we avoid the problem 2x ORDER BY in the main query, because the ORDER BY clause is transferred to the first auxiliary request.
$STH_1 = $DBH_R->query("SELECT c.table_name
FROM v_c_country c
INNER JOIN information_schema.tables i ON i.table_name = c.table_name
ORDER BY c.country_name_pl ASC ");
while (($row_1 = $STH_1 -> fetch_assoc()) != null){
$table_name = $row_1['table_name'];
$stmts_1[] = sprintf("SELECT *,'$table_name' AS table_name, time(date_time) AS time_dt, date(date_time) AS date_dt, MAX(date_time) AS MAXdate
FROM $table_name
WHERE ei_code = '1117' AND (DAY(date_time) != '00')
AND date_time = (SELECT MAX(date_time) FROM $table_name WHERE ei_code = '1117' AND index_released = '1')
");
}
$stmt_1 = implode("\nUNION\n", $stmts_1);
$STH_5_2 = $DBH_R->query($stmt_1);
Often I meet here with the tolerant approach to the questions asked, you know that if someone asks a question that awaits us - looking for - ask for help in solving the problem. I really, really thank all those who reach out a helping hand and give really helpful answer. These people really do happen.
Faily new to php and mysql, this will probably seem very messy.
This is what I came up with:
$query = "show tables like 'whatever%'";
$result = mysql_query($query);
$num_results = mysql_num_rows($result);
for ($i = 0; $i < $num_results; $i++)
{
$row = mysql_fetch_array($result);
$sql=mysql_query("SELECT * FROM ". $row[0] ." WHERE a=(SELECT MAX(a)) AND b=(SELECT MAX(b)) AND c LIKE 'd%' ORDER BY date DESC LIMIT 1");
while($info=mysql_fetch_array($sql)){
echo "...";
}
}
I get the desired value from each table, so x results depending on the amount of tables. What I would like is to have the results of the queried tables but only show the top 10-5 ordered by date/time.
Is this possible with the current script? Is there an easier way (while, number of tables changing constantly)? Is this query method database intensif?
Cheers!
I call constantly changing number of tables having similar structure a design error. also query switch to
$sql=mysql_query("SELECT * FROM $tbl WHERE c LIKE 'd%' ORDER BY a DESC, b DESC, date DESC LIMIT 1");
is a little relief to database.