I use grocery-crud for a simple SQL select
$crud->set_table('lista_ab');
$crud->set_relation('id_ab','lista_ab_term','Expire');
The problem is that it does not make the relation for 'id_ab'
My database looks
CREATE TABLE `lista_ab` (
`id_ab` int(10) NOT NULL,
`Subname` varchar(255) DEFAULT NULL,
`Name` varchar(255) DEFAULT NULL,
`Inregistrat` date DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `lista_ab_term` (
`ID` int(10) NOT NULL,
`id_ab` int(10) DEFAULT NULL,
`Expire` date DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
In final I want to extract Subname and Expire.
You cannot create dropdown list and show field name of the first table : Subname, but you can have as many fields you like to call from the other table and the syntax is really simple.
Just at the 3rd field you will have the symbol { and } . So it will be for example:
$crud->set_relation('id_ab','lista_ab_term','{Expire} - {ID}');
You can use join query like this for your expected results:
SELECT t1.Subname, t2.Expire FROM lista_ab t1 LEFT JOIN lista_ab_term t2 ON t1.id_ab = t2.id_ab
Or In Codeigniter
$this->db->select('lista_ab.Subname,
lista_ab_term.Expire');
$this->db->from('lista_ab');
$this->db->join('lista_ab_term', 'lista_ab.id_ab= lista_ab_term.id_ab');
$q = $this->db->get();
Related
I am trying to write a script that will allow the user to select a list of fields to be displayed from different column/table in a database. This script will need be able to generate the full query and execute it.
I am able to select the field and add the proper where clause. However, I am being challenged on how to generate the ON clause which is part of the JOIN statement.
Here is what I have done so far.
First, I defined 3 tables like so
-- list of all tables available in the database
CREATE TABLE `entity_objects` (
`object_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`object_name` varchar(60) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`object_description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`object_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-- list of all tables available in the database
CREATE TABLE `entity_definitions` (
`entity_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`display_name` varchar(255) NOT NULL,
`entity_key` varchar(60) NOT NULL,
`entity_type` enum('lookup','Integer','text','datetime','date') CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`object_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`entity_id`),
KEY `object_id` (`object_id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
-- a list of the fields that are related to each other. For example entity 12 is a foreign key to entity 11.
CREATE TABLE `entity_relations` (
`relation_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`entity_a` int(11) unsigned NOT NULL,
`entity_b` int(11) unsigned NOT NULL,
`relation_type` enum('1:1','1:N') NOT NULL DEFAULT '1:1',
PRIMARY KEY (`relation_id`),
UNIQUE KEY `entity_a` (`entity_a`,`entity_b`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
To get a list of the relations that are available, I run this query
SELECT
CONCAT(oa.object_name, '.', ta.entity_key) AS entityA
, CONCAT(ob.object_name, '.', tb.entity_key) AS entityB
FROM entity_relations as r
INNER JOIN entity_definitions AS ta ON ta.entity_id = r.entity_a
INNER JOIN entity_definitions AS tb ON tb.entity_id = r.entity_b
INNER JOIN entity_objects AS oa ON oa.object_id = ta.object_id
INNER JOIN entity_objects AS ob ON ob.object_id = tb.object_id
I am having hard time trying to figure out how to generated the JOIN statement of the query. I am able to generate the SELECT ..... and the WHERE... but need help trying to generate the ON.... part of the query.
My final query should look something like this
SELECT
accounts.account_name
, accounts.industry_id
, accounts.primary_number_id
, accounts.person_id
, industries.industry_id
, industries.name
, contact_personal.first_name
, contact_personal.person_id
, account_phone_number.number_id
FROM accounts
LEFT JOIN industries ON industries.industry_id = accounts.industry_id
LEFT JOIN contact_personal ON contact_personal.person_id = accounts.person_id
LEFT JOIN account_phone_number ON account_phone_number.number_id = accounts.primary_number_id
WHERE industries.name = 'Marketing'
I created a SQL Fiddle with my MySQL code.
How can I define the ON clause of the join statement correctly?
It is completely unnecessary to create these tables, mysql can handle all of this for you so long as you are using the InnoDB storage engine by using foreign keys.
list all tables on current database
SHOW TABLES;
get list of columns on a given table
SELECT
*
FROM
information_schema.COLUMNS
WHERE
TABLE_SCHEMA = :schema
AND TABLE_NAME = :table;
get list of relationships between tables
SELECT
*
FROM
information_schema.TABLE_CONSTRAINTS tc
INNER JOIN
information_schema.INNODB_SYS_FOREIGN isf ON
isf.ID = concat(tc.CONSTRAINT_SCHEMA, '/', tc.CONSTRAINT_NAME)
INNER JOIN
information_schema.INNODB_SYS_FOREIGN_COLS isfc ON
isfc.ID = isf.ID
WHERE
tc.CONSTRAINT_SCHEMA = :schema
AND tc.TABLE_NAME = :table;
Okay so now its display results like 3 times in a row
$user_apps = mysql_query("SELECT a.name,a.download_url FROM user_apps as ua LEFT JOIN
apps as a ON (ua.app_id=a.app_id)
WHERE ua.user_id='$user_id'") or die(mysql_error());
while($raw = mysql_fetch_array($user_apps)){
$name = $raw['name'];
$url = $raw['download_url'];
echo $name;
echo "<br />";
echo $url;
}
Database Table Structure(since I am new to the site and did not know how to display the table structure I just exported the sql)
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;
CREATE TABLE IF NOT EXISTS `user_apps` (
`user_id` int(11) NOT NULL,
`app_id` int(11) NOT NULL,
KEY `user_id` (`user_id`,`app_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `apps` (
`app_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`description` text NOT NULL,
`icon` varchar(255) NOT NULL,
`download_url` varchar(255) NOT NULL,
`default` int(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`app_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ;
I'v tried different Join types but that does not seem to work.
Used the join query for get the result check bellow example query
$user_apps = mysql_query("SELECT DISTINCT a.name,a.download_url FROM user_apps as ua LEFT JOIN apps as a ON (ua.app_id=a.app_id) WHERE ua.user_id='$user_id'") or die(mysql_error());
while($raw = mysql_fetch_array($user_apps)){
$name = $raw['name'];
$url = $raw['download_url'];
echo $name;
echo $url;
}
change the join type as per your requirement. the above query for only example
INNER JOIN: Returns all rows when there is at least one match in BOTH
tables
LEFT JOIN: Return all rows from the left table, and the matched rows
from the right table
RIGHT JOIN: Return all rows from the right table, and the matched
rows from the left table
FULL JOIN: Return all rows when there is a match in ONE of the tables
more about join click here
AND also check this http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
You have used single quotes in query at user_id='$user_id' .
Are you sure your user_id is char, varchar or text? Just print_r($user_apps) and check it has any records or not? If user_id is int,tinyin than remove single quote.
I'm making a simple PHP Forum, whereby tags are created alongside the main topic.
The table looks like this:
CREATE TABLE IF NOT EXISTS `topic` (
`topic_id ` int(100) NOT NULL AUTO_INCREMENT,
`topic_head` varchar(5) NOT NULL,
`topic_body` varchar(20) NOT NULL,
`topic_tag` varchar(20) NOT NULL,
`topic_date` varchar(20) NOT NULL,
`topic_owner` varchar(20) NOT NULL,
PRIMARY KEY (`topic_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
Specifically for the tags, I'll be performing a select query in the form of:
$tags = mysql_query("SELECT DISTINCT topic_tags
FROM forum_topics")
while($tags = mysql_fetch_assoc($tags){
$split_tags = "$tags";
$pieces = explode(",", $split_tags);
Currently, topic_tags are in the format tag1,tag2,tag3,tag4
How can I have it in such a way that each topic tag will be associated with each topic?
If I've understood correctly, what you want is another table for tags and then a third table to store the relationships. So:
CREATE TABLE `tags` (
`t_id` int(11) NOT NULL AUTO_INCREMENT,
`t_text` varchar(150) NOT NULL,
`t_datetime` datetime NOT NULL,
PRIMARY KEY (`t_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE `tag_pairs` (
`tp_id` int(11) NOT NULL AUTO_INCREMENT,
`tp_topic_id` int(11) NOT NULL,
`tp_tag_id` int(11) NOT NULL,
`tp_datetime` datetime NOT NULL,
PRIMARY KEY (`tp_id`),
FOREIGN KEY (`tp_topic_id`) REFERENCES topic('topic_id'),
FOREIGN KEY (`tp_tag_id`) REFERENCES tags('t_id')
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Then, to get tags for a topic based on its ID ($THIS_ID):
$query = mysql_query("
SELECT tags.t_text
FROM tags, tag_pairs, topic
WHERE topic.topic_id = '$THIS_ID'
AND tag_pairs.tp_topic_id = topic.topic_id
AND tag_pairs.tp_tag_id = tags.t_id
");
Call the columns just: id, head, body, tag_id (FK), date and user_id (FK)
This is much more understandable and also easier to use. Let me explain:
Right now you are using the columns as: topic_id, but it should be: topic.id. How do you get this? By simply using the tablename + column. So when the table is called topics and you have a column called id, you can use it by saying: topics.id. In the answer above from da5id, I can see that he is using topics.topic_id, a bit overkill isn't it? ;)
Also, read this article about database normal form 3 and google a bit yourself with database+3nf
Trying to track outbound clicks on advertisements, but im having troubles constructing the query to compile all the statistics for the user to view and track.
I have two tables, one to hold all of the advertisements, the other to track clicks and basic details on the user. ip address, timestamp, user agent.
I need to pull all of map_advertisements information along with Unique Clicks based on IP Address, and Total Clicks based on map_advertisements.id to be showin in a table with rows. 1 row per advertisement and two of its columns will be totalClicks and totalUniqueClicks
Aside from running three seperate queries for each advertisement is there a better way to go about this?
I am using MySQL5 PHP 5.3 and CodeIgniter 2.1
#example of an advertisements id
$aid = 13;
SELECT
*
count(acl.aid)
count(acl.DISTINCT(ip_address))
FROM
map_advertisements a
LEFT JOIN map_advertisements_click_log acl ON a.id = acl.aid
WHERE
a.id = $aid;
map_advertisements
-- ----------------------------
-- Table structure for `map_advertisements`
-- ----------------------------
DROP TABLE IF EXISTS `map_advertisements`;
CREATE TABLE `map_advertisements` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`youtube_id` varchar(255) NOT NULL,
`status` int(11) NOT NULL DEFAULT '1',
`timestamp` int(11) NOT NULL,
`type` enum('video','picture') NOT NULL DEFAULT 'video',
`filename` varchar(255) NOT NULL,
`url` varchar(255) NOT NULL,
`description` varchar(64) NOT NULL,
`title` varchar(64) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
map_advertisements_click_log
-- ----------------------------
-- Table structure for `map_advertisements_click_log`
-- ----------------------------
DROP TABLE IF EXISTS `map_advertisements_click_log`;
CREATE TABLE `map_advertisements_click_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`aid` int(11) NOT NULL,
`ip_address` varchar(15) NOT NULL DEFAULT '',
`browser` varchar(255) NOT NULL,
`timestamp` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=latin1;
A problem seems to be in your query there is no column with the name totalClicks in your table and distinct keyword is also used incorrectly. Try this:
SELECT *, count(acl.id) as totalClicks, count(DISTINCT acl.ip_address) as uniqueClicks
FROM map_advertisements a
LEFT JOIN map_advertisements_click_log acl ON a.id = acl.aid
WHERE a.id = $aid;
I've googled my question and read through a bunch of forum posts but I've yet to find the answer I'm looking for hopefully someone here can help me out.
For a project I'm building I've set up the following 3 tables; users, projects and projectUsers.
I've set up a form where I can add users to projects by saving the userID and the projectID in the projectUsers table nothing special so far. The form contains a select element with userIDs that can be connected to a projectID (hidden field).
This form element is filled with a query set up with Zend_Db_Select it selects all the users from the users table and adds it to the select. However I want to filter that result so it excludes all of the users already added to that specific project.
Short version: I have a select element with users filled with a resultset from a (Zend_db_select) database query I want that resultset to be stripped from certain userIDs.
For extra reference the table scheme below:
CREATE TABLE IF NOT EXISTS `projects` (
`projectID` int(11) NOT NULL AUTO_INCREMENT,
`projectName` varchar(255) NOT NULL
PRIMARY KEY (`projectID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `projectUsers` (
`projectUserID` int(11) NOT NULL AUTO_INCREMENT,
`projectID` int(11) NOT NULL,
`userID` int(11) NOT NULL
PRIMARY KEY (`projectUserID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `users` (
`userID` int(11) NOT NULL AUTO_INCREMENT,
`userFirstName` varchar(255) DEFAULT NULL,
`userLastName` varchar(255) DEFAULT NULL
PRIMARY KEY (`userID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Thanks in advance!
addint to Soica Micea ans
$blackList = array(1,3,5,6); //user id which you want to exclude
$db->select()->from('users', '*')
->joinLeft('projectUsers', 'projectUsers.projectUserID = users.userID', null)
->where('projectUsers.projectID = ?', someProjectID)
->where('projectUserID is null')
->where('users.userID not in (?)', implode(',',$blackList))
->query()->fetchAll();
This will select all users that have not been added to a project and ignore users from arrayOfUserIds
select()->from('users', '*')
->joinLeft('projectUsers', 'projectUsers.projectUserID = users.userID', null)
->where('projectUsers.projectID = ?', someProjectID)
->where('projectUserID is null')
->where('users.userID not in (?)', arrayOfUserIds)
->query()->fetchAll();