i have some reference to record for a given article. a reference might be of type an article, book, thesis etc..
each might have different attributes, e.g.
//article_refs table
ID Article_ID Article_Title Author_Name ...
1 1 title1 author1
2 1 title2 author2
//thesis_refs table
ID Article_ID Thesis_Title Thesis_Publisher ...
1 1 thesis1 publisher1
2 1 thesis2 publisher2
//ref_types table
ID Article_ID ReferenceType
1 1 book
2 1 article
3 1 article
4 1 book
when i insert into one of the tables, i first into ref_type table with its type (book, article). then insert whichever table it belongs. (e.g. if it is an article, insert into article table)..
now, i have to be able list references in order.
$sql=mysql_query("SELECT * FROM ref_types
WHERE $article_ID=Article_ID ORDER BY ID ASC");
while($row = mysql_fetch_array($sql)){
$counter=1;
if($row[2]=="thesis"){
$sqlthesis=mysql_query("SELECT * FROM thesis_refs
WHERE $article_ID=Article_ID
ORDER BY ID ASC");
while($thesis_row = mysql_fetch_array($sqlthesis)){
echo "record $counter: ";
echo $row[2];
echo ", ";
echo $thesis_row[2];
echo "<BR>";
$counter++
}
}elseif.....
this way it lists all thesis records then lists article table etc..
record 1: book1
record 2: book2
record 3: article1
record 4: article2
i know it is simply because of while loop, but how to get this (same order with ref_types table..)??
record 1: book1
record 2: article1
record 3: article2
record 4: book2
any help is appreciated.
thanks in advance..
In addition to having ReferenceType column in ref_types table, you also need a Reference_ID column that refers to the actual ID in the corresponding table as a foreign key.
//ref_types table
ID Article_ID ReferenceType Reference_ID
1 1 book 1
2 1 article 1
3 1 article 2
4 1 book 2
Then, you can avoid a WHILE loop and let MySQL do the work for you with JOINs:
SELECT CONCAT('record ', rt.ID, ': ',
COALESCE(ar.Article_Title, tr.Thesis_Title, br.Book_Title))
FROM ref_types rt
LEFT JOIN article_refs ar
ON rt.ReferenceType = 'article' AND ar.ID = rt.Reference_ID
LEFT JOIN book_refs br
ON rt.ReferenceType = 'book' AND br.ID = rt.Reference_ID
LEFT JOIN thesis_refs tr
ON rt.ReferenceType = 'thesis' AND tr.ID = rt.Reference_ID
Yields the result:
record 1: book1
record 2: article1
record 3: article2
record 4: book2
Instead of printing the data right away, store it in an array based of the ref_thesis id. e.g
$data = array();
$sql=mysql_query("SELECT * FROM reftypes
WHERE $article_ID=Article_ID ORDER BY ID ASC");
while($row = mysql_fetch_array($sql)){
$counter=1;
if($row[2]=="thesis"){
$sqlthesis=mysql_query("SELECT * FROM ref_thesis
WHERE $article_ID=Article_ID
ORDER BY ID ASC");
while($thesis_row = mysql_fetch_array($sqlthesis)){
$data[ $row['id'] ] = $row;
}
}elseif.....
that way the rows in the $data array will be in the order based on the id in the ref_thesis table.
That said, I think you should go back and think about the db schema you have. You should be able to get what you want with a few simple JOIN statements in a single query, rather than querying the db inside a while loop
Related
I got the two tables(Table1 and Table2):
Table1:
id hits url
1 11 a
2 5 b
3 6 c
4 99 d
5 14 e
Table2:
id url 2014.04.13 2014.04.14
1 a 0 5
2 b 0 1
3 c 0 3
4 d 0 60
5 e 0 10
hi all,
Table1 one contains the actual hits(which are always up-to-date) and Table2 to statistics(which are done every day at midnight). The columns id(unique number) and url are in both tables the same. So they got the same amount of rows.
So i create every day a new column(with the date of today) and copy the column hits from the table 'Table1' into the new created column into the table 'Table2'
First i alter Table2:
$st = $pdo->prepare("ALTER TABLE Table2 ADD `$today_date` INT(4) NOT NULL");
$st->execute();
Then i cache all entries i need from Table1:
$c = 0;
$id = array();
$hits = array();
$sql = "SELECT id, hits FROM Table1 ORDER BY id ASC";
$stmt = $pdo->query($sql);
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$id[$c] = $row['id'];
$hits[$c] = $row['hits'];
$c++;
}
At last i update Table2:
for ($d = 0 ; $d < $c ; $d++)
{
$id_insert = $id[$d];
$sql = "UPDATE DOWNLOADS_TEST SET `$datum_det_dwnloads`=? WHERE id=?";
$q = $pdo->prepare($sql);
$q->execute(array($hits[$d], $id[$d]));
if($q->rowCount() == 1 or $hits[$d] == 0) // success
$hits[$d] = 0;
else // error inserting (e.g. index not found)
$d_error = 1; // error :( //
}
So what i need is to copy(insert) a column from one table to another.
The two tables are having ~2000 elements and the copying as described above takes around 40 sec. The bottleneck is the last part (inserting into the Table2) as i found out.
One thing i found is to do multiple updates in one query. Is there anything i can do besides that?
I hope you realise that at some point your table will have irrational number of columns and will be highly inefficent. I strongly advise you to use other solution, for example another table that holds data for each row for each day.
Let's say you have a table with 2000 rows and two columns: ID and URL. Now you want to know the count of hits for each URL so you add column HITS. But then you realise you will need to know the count of hits for each URL for every date, so your best bet is to split the tables. At this moment you have one table:
Table A (A_ID, URL, HITS)
Now remove HITS from Table A and create Table B with ID and HITS attributes). Now you have:
Table A (A_ID, URL)
Table B (B_ID, HITS)
Next move is to connect those two tables:
Table A (A_ID, URL)
Table B (B_ID, A_ID, HITS)
Where A_ID is foreign key to attribute "A_ID" of Table A. In the end it's the same as first step. But now it's easy to add date attribute to Table B:
Table A (A_ID, URL)
Table B (B_ID, A_ID, HITS, DATE)
And you have your solution for database structure. You will have a lot of entries in table B, but it's still better than a lot of columns. Example of how it would look like:
Table A | A_ID | URL
0 index
1 contact
Table B | B_ID | A_ID | HITS | DATE
0 0 23 12.04.2013
1 1 12 12.04.2013
2 0 219 13.04.2013
3 1 99 13.04.2013
You can also make unique index of A_ID and DATE in Table B, but I prefer to work on IDs even on linking tables.
I need a small hint... I've got 2 Tables.
Table 1 gets data from an external api.
Table 2 is static.
Table 1: data
id name status ratio import_id
1 Test online 3 1
2 Tee online 2 1
3 Test online 1 2
4 Tee online 0.01 2
5 Test offline 4 3
6 Teee online 3 3
7 Teet online 1 3
Table 2: names
id name tag active
1 Test t1 1
2 Tee t2 1
3 Teee t3 0
4 Teet t4 1
I want to have the ID from the table names (to write into another table and execute a cronjob)
Explanation Table 1:
id - AI
name - just the name
status - if the entry is active
ratio - the main select
import_id - every 10 minutes I do import from json (~40 entries)
what i've got:
$result = mysql_query("
SELECT
import_id
FROM
data
ORDER BY id DESC LIMIT 1");
while($raw = mysql_fetch_object($result))
{
$the_id = $raw->import_id;
echo $the_id;
}
Now I've got the ID and try to get the latest entry (import_id) with the highest ratio:
$c_result = mysql_query("
SELECT
name, active, ratio, import_id
FROM
data
WHERE
active = '1' AND import_id = '$the_id'
ORDER BY
ratio DESC LIMIT 1");
while($chosen = mysql_fetch_object($c_result))
{
$the_c = $chosen->name;
echo $the_c;
}
That works flawless.
But it is possible that one of the 40 entries provided by api is not in my table "names" or it is not marked as "active".
But I only want the names.id of
the name with the highest ratio
which is in my table "names"
which is marked as active in "names"
and the data.status is online
which is from the latest import (highest import_id)
and write it to another table.
I thought about a LEFT JOIN but if the names.name is not in the table "names" i just get an empty result.
Have you got a hint in the right direction?
SELECT d.name, active, ratio, import_id
FROM data d
JOIN names n ON d.name = n.name
WHERE import_id = (SELECT import_id
FROM data
ORDER BY id DESC
LIMIT 1)
AND d.status = 'online'
AND n.active = 1
ORDER BY ratio DESC
LIMIT 1
DEMO
I have a database that looks like this with two tables
Items
id | Title
-----------------------------
1 Bus
2 Plane
3 Jet
4 Shoes
5 Chair
Sorting
id | CatID | ItemID | SortOrder
-------------------------------------------------------------------------------
1 3 3 3
2 3 2 1
3 3 4 2
4 3 1 0
5 4 5 4
I can't figure out how to list the Titles of the ITEMS table based on the "SortOrder" Column of the SORTING table.
Here is what I tried so far:
SELECT *
FROM Items
LEFT JOIN Sorting ON Items.id = Sorting.ItemID
WHERE Sorting.CatID = 3
ORDER BY Sorting.SortOrder
I'm not sure what I'm doing wrong
EDIT
It looks like the MySQL query is correct, the problem is happening because when I output the $row['id'] of the Items Table it is incorrect. I have an Ajax PHP update that is updating the database based on the id of an li tag.
Any ideas why the $row['id'] is outputting incorrectly? I think it has something to do with the Items.id = Sorting.ItemID
This works as expected - SQLFiddle DEMO:
SELECT i.*, s.SortOrder
FROM items i, sorting s
WHERE i.id = s.ItemID
AND s.CatID = 3
ORDER BY s.SortOrder
Try
SELECT *
FROM Items
LEFT JOIN Sorting ON Items.id = Sorting.ItemID
WHERE Sorting.CatID = 3
ORDER BY Sorting.SortOrder ASC
add DESC or ASC in ORDER BY clause.
if you use ASC then sorted result will be 0 1 2 3 4 for SortOrder.
sample php code to get title
<?php
$query = mysqli_query(above_query)or die(mysqli_error());
while($result = mysqli_fetch_assoc($query))
{
echo $result['title']. '<br/>';
}
I have a table that looks like this
id | itemID | catID | Title
----------------------------------------------------------------------------
0 3 4 Hello
1 3 6 Hello
2 4 4 Yo
3 4 8 Yo
4 5 2 Hi
5 1 3 What
I want to do a MySQL PHP Select that only gets one occurrence of the itemID. As you can see they are the same item, just in different categories.
This is what I tried
SELECT * FROM Table GROUP BY itemID
That didn't seem to work, it still just shows duplicates.
Is this what you are looking for? http://www.sqlfiddle.com/#!2/5ba87/1
select itemID, Title from test group by itemID;
As far as MySQL is concerned, the data is all unique, since you want all of the columns. You have to be more specific.
Do you just want the itemID (or other column)? Then say so:
select [column] from Table GROUP BY itemID
Do you want the last entry of a particular item ID? Then say that:
select * from Table where itemID = 1 ORDER BY id DESC
Or the first one?
select * from Table where itemID = 1 ORDER BY id
If none of these are what you want, then you probably need to restructure your tables. It looks like you want different categories for your items. If so, then you'll want to split them out into a new join table, because you have a many-to-many relationship between Items and Categories. I recommend reading up on database normalization, so you're not duplicating data (such as you are with the titles).
If you want everything for the distinct itemIDs, you could certainly take a long route by doing one selection of all of the distinct itemIDs, then doing a series of selections based on the first query's results.
select distinct(`itemID`) from Table
Then in your PHP code, do something like this:
while ($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
$itemID = $row['itemID'];
$sql2 ="SELECT * FROM Table WHERE 1 and `itemID`=\"$itemID\" limit 1";
$result2 = #mysql_query($sql2, $connection);
while ($row2 = mysql_fetch_array($result2))
{
$id = $row2['id'];
$itemID = $row2['itemID'];
$catID = $row2['catID'];
$Title = $row2['Title'];
}
}
I have two tables: Stores and Items. The relationship is: Stores 1---* Items
In PHP/MySQL what would be the best (fastest/simplest) way to check if a particular item belongs to a particular store.
In other words given for example:
$store_id = 1;
$item_id = 12;
I want to check if item 12 belongs to store 1 (and not some other store).
I usually do a select on Items matching both the store_id and item_id and limit the results to 1. Then check how many rows (0 or 1) were returned with mysql_num_rows. Is there a better way?
Update:
Both tables have an "id" column. The Items table has a "store_id" column.
SELECT COUNT(*) AS count
FROM stores JOIN items USING(store_id)
WHERE item_id = 12
AND store_id = 1
Then you'd get the results, and check of count > 0 or not. However, if I'm getting your DB design right, then you have a very messed up database.
From what you describe, an item can only exist in one store. So my guess of the general layout here would be like this:
STORE ITEM
----- ----
store_id ---| item_id
store_name |--- store_id
... item_name
...
Is this correct? An item can never exist except in the one store? So if it's a screwdriver, every store would need a different item_id to hold it?
A better design would be:
STORE STORE_ITEM ITEM
----- ---------- ----
store_id ------- store_id |------ item_id
store_name item_id ---| item_name
... ...
With a query of
SELECT COUNT(*)
FROM store JOIN store_item USING(store_id)
JOIN item USING(item_id)
WHERE store_id = 1
AND item_id = 12
Both tables have an id, Items has a store_id
SELECT COUNT(*) FROM Items WHERE store_id = $store_id AND id = $item_id
$r = mysql_query("select NULL from Item where storeID = '$store_id' and ItemID = '$item_id'");
if (mysql_fetch_row($r))
{
it belongs...
}
For fun, I'll throw in a one-liner check:
// if item belongs to store
if (current(mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM Items WHERE store_id = $store_id AND id = $item_id"), MYSQL_NUM)))) {
// it belongs!
}