Extract columns names resulting by query - mysql

is it possible to get the columns names resulting by a query?
So (for example) if I have this query:
SELECT Id AS IdNumber,
(SELECT COUNT(*) FROM tab2 WHERE IdRif = T1.Id) AS TotCount
FROM tab1 T1
I'd like to get:
IdNumber
TotCount
I saw MySQL query to get column names? (and also other questions) but I wasn't able to use it for what I need.

If your query returns results just use the object(fetch_object) / array (fetch_assoc) from the row and use array_keys($row)
if no rows are returned use http://php.net/manual/en/mysqli-result.fetch-field-direct.php
$result = $db->query($sql);
$i = 0;
while ($i < $db->field_count) {
$info = $result->fetch_field_direct($i++);
echo $info->name;
}
as an example

You can fetch the query result into an Associative Array using mysql_fetch_array($result,MYSQL_ASSOC) or $result->fetch_array(MYSQLI_ASSOC) or whatever method you are using, so that the Key=>Value pair of your Associative Array would be your ColumnName=>ColumnValue.
So, irrespective of whether you are using mysql or mysqli, you would be using the same logic to get the column names.

Related

How to retrieve data from mysql db by passing an array

I have an dynamic array of id which is passed by frontend. I need to fetch data from mysql db where the tuples ids are match with the ids which i pass.
Example Id array: [6, 7, ...]
The number of items can be vary according to different requests.
SELECT expense_type, expense_category FROM expense_type WHERE expense_category_id=id1 OR expense_category_id=id2;
id1, id2 are the ids which comes from the frontend. (6,7,...)
There can be multiple ids which comes from the frontend.
could i please know is there a way to fetch data from one query in such situation.
Or else do i have to write multiple queries to execute?
You need to make query by using that multiple ids's array.
something like below
query = 'SELECT expense_type, expense_category FROM expense_type WHERE expense_category_id IN (`;
forEach(ids as id) {
query += id + ','
}
run query..
To select data based on an array of values you can use the IN-keyword. In your case it would look like this:
SELECT expense_type, expense_category
FROM expense_type
WHERE expense_category_id IN ('id1', 'id2');
you can easily use an IN.
also try to use Join. so the accuracy of the query will get increase.
SELECT expense_type, expense_category
FROM expense_type
WHERE expense_category_id IN ('id1', 'id2');

How to use an excludent IN?

I have the following code:
SELECT stores_tb.stores, sum(products_tb_tb.prices)
from products_tb
inner join stores_tb
on products_tb.id_store = stores_tb.id_store
where products_tb.barcode IN ($barcodes)
group by stores_tb.stores
order by sum(products_tb.prices)
Being the $barcodes an array (already converted to a string) that I receive via ajax in a php file that executes the MySQL.
The thing is that the IN is inclusive, using OR for each of the array values, meaning that if one of the stores required on the SELECT have one, but not all of the barcodes in the array, it will be shown.
I wanna know if there is a function like the IN (or a way to use the IN function) in which it will return only the stores that have all of the barcodes passed in the array, the equvilant of using AND instead of OR for each of the array values.
You can do this with a having clause:
select s.stores, sum(p.prices)
from products_tb p join
stores_tb s
on p.id_store = s.id_store
where p.barcode IN ($barcodes)
group by s.stores
having count(distinct p.barcode) = $n -- the number of codes that need to match
order by sum(p.prices);
The $n value is the length of the $barcodes list (strictly speaking, the number of unique items in it).
Instead of an array and an IN clause You could use a subselect and the ALL operator
SELECT stores_tb.stores, sum(products_tb_tb.prices)
from products_tb
inner join stores_tb
on products_tb.id_store = stores_tb.id_store
where products_tb.barcode = ALL (
select barcode from my_table )
)
group by stores_tb.stores
order by sum(products_tb.prices)
https://dev.mysql.com/doc/refman/5.7/en/any-in-some-subqueries.html
https://dev.mysql.com/doc/refman/5.7/en/all-subqueries.html

Show each records of groupby sql query

I have an ads table like this:
id adid approveby
1 10 MR A
2 11 MR A
3 12 MR B
I would like to count total record of MR A and echo each record out so I have this sql query:
$sql = "SELECT *, count(*) AS `totaladsapproved` FROM ads GROUP BY approveby";
$result = $conn->prepare($sql);
$result->execute();
foreach ($result as $row){
echo "Name: $row[approveby]"." - Total ads approved: $row[totaladsapproved] <br>";
for($i=0;$i<$row['totaladsapproved'];$i++){
echo "Ad ID: $row[adid] <br>"
}
}
But it only shows adid 10 twice. Here is the result i got:
Name: MR A - Total ads approved: 2
AD ID: 10
AD ID: 10
I would like to show AD ID 10 and then AD ID 11...What should I do to achieve this?
Many thanks
your query is grouping so you would not see each id
use following, this will give you count of total "aproveby" present for each row
SELECT id,
adid,
approveby,
(select count(*) from ads where approveby
= t1.approveby) AS `totaladsapproved`
FROM ads t1
if you want to restrict to MR A you can use where clause
The code has a lot of problems. They are addressed below one by one.
Undefined $i
Your code reads:
foreach ($result as $row){
echo "Name: $row[approveby]"." - Total ads approved: $row[totaladsapproved] <br>";
for ($i; $i < $row['totaladsapproved']; $i ++) {
echo "Ad ID: $row[adid] <br>";
}
}
First thing to notice is that $i is not initialized but you use it to iterate in a for() loop. PHP is nice and, besides showing you a notice you don't care of, because of the numeric context it uses 0 instead of NULL on the first loop when it handles $i to check the condition and to increment $i.
The correct way to do it is:
for ($i = 0; $i < $row['totaladsapproved']; $i ++) {
not only because of what I mentioned above but also because using your code, on the next foreach() iteration, $i starts with 2 and the for() loop skips the first two iterations.
The logic error in the loops
You get one row in variable $row but then you just print it 2 times (or as many times $row['totaladsapproved'] says) without getting the subsequent rows from the result set.
To fix it you could get new rows from the result set inside the for() loop. I don't provide code here because it doesn't matter, the query is wrong anyway.
General considerations about the queries that use GROUP BY
If you want to get the records then do not use GROUP BY. GROUP BY approveby produces a single row from all the rows that have the same value for approveby.
In the SELECT clause of a query that has a GROUP BY clause you can use only:
the columns that also appear in the GROUP BY clause;
other columns that are functionally dependent on the fields that appear in the GROUP BY clause; this means you can use any column of the table only if the table's PK or an UNIQUE INDEX of it appears in the GROUP BY clause;
any column of the table if it is used as an argument of aGROUP BY aggregate function.
Any column that appear in the SELECT clause and is not described in the list above renders the query invalid (according to the SQL standard).
MySQL extends the standard and allows such invalid queries (as long as they are syntactically correct, of course) but it does not guarantee anything about the values of these columns returned in the result set.
... a MySQL extension to the use of GROUP BY is to permit the SELECT list, HAVING condition, or ORDER BY list to refer to nonaggregated columns even if the columns are not functionally dependent on GROUP BY columns. This causes MySQL to accept the (...) query. In this case, the server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate, which is probably not what you want.
The query is incorrect
Back to your query, because the columns id and adid are not included in the list above, using * in the SELECT list renders the query invalid and the values returned for columns id and adid indeterminate.
In your case it happened that for approvedby == 'MR A', MySQL decided to return (1, 10) for (id, adid). It could return (2, 11) instead tomorrow, after you add or remove some rows from the table (or when the table is dumped and imported on a different server). It could even return (1, 11) and it is still right. It could even return -1 or NULL or whatever value it wants and you still cannot blame it because indeterminate is something that is not settled or decided.
The correct query
The correct query for your case is as simple as:
SELECT * FROM ads ORDER BY approveby
Using ORDER BY is important to get the rows having the same value for approveby one next to the other. Then, in the PHP code you run through the returned result set, count the rows for each value of approveby, store it in another list or do whatever you want with it.
$howMany = array(); // store the number of rows in each group
$current = '--fake--'; // the current group (use a value that does not appear in the data)
$count = 0; // the number of rows in the current group
foreach ($result as $row) {
// Check if a new group started
if ($row['approvedby'] != $current) {
// Store the value for the current 'approveby'
$howMany[$current] = $count;
// Start counting for the new value of 'approvedby'
$current = $row['approveby'];
$count = 0;
}
// Count the new occurrence
$count ++;
}
// Store the number of rows from the last group
$howMany[$current] = $count;
// Remove the fake value inserted on the first loop
unset($howMany['--fake--']); // Use the initial value of $current
If you don't need the number of rows in each group before enumerating the rows in the group then your code becomes even simpler: remove from the code above all the references to variable $howMany.

MySql dynamic column name

[major edit to make things clear]
I want to write a query that returns a dynamic column name like this:
SELECT
f2 AS
(
SELECT column_name
FROM column_names_tbl
WHERE column_name = "experience"
limit 0,1
)
FROM some_table
so that would output the same as this:
SELECT
f2 AS experience
FROM some_table
This is no correct SQL syntax, even because the two queries (the selected field and it's alias) are both subqueries and unrelated to each other. So, there's also no possibility for mysql to distinguish what name you want to connect to what value, even if the syntax was correct...
You already use a more or less normalized relational table, so I suggest the following solution:
you select the revision ID and name in a separate query; store them in PHP and use them for whatever you want
next, you evaluate the following query into a separated result set: SELECT ps.keyname, psv.keyvalue FROM page_setting_values AS psv INNER JOIN page_settings AS ps ON ps.id = psv.setting_id WHERE psv.page_revision_id = :revision with :revision representing your revision id
you may now assemble an associated array from that result set:
$settings = [];
$result = $db->executeQuery('...')->fetchAll();
foreach($result as $setting)
{
$settings[$setting['keyname']] = $setting['keyvalue'];
}
Hope that helps ;)

How to get the row number from a while loop of mysql_fetch_array for each loop?

I have a simple while loop like this
while($row = mysql_fetch_array($result)){
}
It fetches many rows one by one and it is fine.
But i have add some extra features according to the row number.
when row number=1( first row)-do something
when row number=2( second row)-do something new
how can i get that ROW NUMBER of the each row?
Add a count variable:
$count = 1;
while ( $row = mysql_fetch_array( $result ) ) {
// do your work here
$count++;
}
You will have to include the row number in your select SQL. So updated your MySQL SQL Statement that fetches the rows, to include the row number as follows.
select #rownum:=#rownum+1 ‘row_number’, * from your_table, (SELECT #rownum:=0) r
This will create a variable rownum, initialize with value 0 & increase it by 1 for every record. Each row will have a column called row_number with ascending number starting from 1.
Then in your while... loop check for this row_number value and do processing accordingly.
Reference: See this post for another approach that involves creating a separate variable in SQL statement.
add an extra field in the select called row like this
SELECT #row:=IFNULL(#row,0)+1 as row,
your_columns
FROM your_tables