I have two tables in one database, table one called: ci_admin, and table two called active_ingredient.
I want to get user data from the active_ingredient table where user_id equals admin_id from ci_admin table using the current user session.
this code, get data for all user, I need the data inserted by the user only:
$wh =array();
$SQL ='SELECT * FROM active_ingredient';
$wh[] = "SELECT 1
FROM ci_admin
WHERE ci_admin.admin_id = active_ingredient.user_id";
if(count($wh)>0)
{ $WHERE = implode(' and ',$wh);
return $this->datatable->LoadJson($SQL,$WHERE);
}
else
{
return $this->datatable->LoadJson($SQL);
}
Try this, it will help you.
$this->db->select('ai.*,ca.*');
$this->db->from('active_ingredient ai');
$this->db->join('ci_admin ca', 'ca.admin_id = ai.user_id', 'left');
$this->db->where($data); //pass the session data for exact filter
$query = $this->db->get();
return $query->result();
I'm looking to update multiple rows in PostgreSQL in one statement. Is there a way to do something like the following?
UPDATE table
SET
column_a = 1 where column_b = '123',
column_a = 2 where column_b = '345'
You can also use update ... from syntax and use a mapping table. If you want to update more than one column, it's much more generalizable:
update test as t set
column_a = c.column_a
from (values
('123', 1),
('345', 2)
) as c(column_b, column_a)
where c.column_b = t.column_b;
You can add as many columns as you like:
update test as t set
column_a = c.column_a,
column_c = c.column_c
from (values
('123', 1, '---'),
('345', 2, '+++')
) as c(column_b, column_a, column_c)
where c.column_b = t.column_b;
sql fiddle demo
Based on the solution of #Roman, you can set multiple values:
update users as u set -- postgres FTW
email = u2.email,
first_name = u2.first_name,
last_name = u2.last_name
from (values
(1, 'hollis#weimann.biz', 'Hollis', 'Connell'),
(2, 'robert#duncan.info', 'Robert', 'Duncan')
) as u2(id, email, first_name, last_name)
where u2.id = u.id;
Yes, you can:
UPDATE foobar SET column_a = CASE
WHEN column_b = '123' THEN 1
WHEN column_b = '345' THEN 2
END
WHERE column_b IN ('123','345')
And working proof: http://sqlfiddle.com/#!2/97c7ea/1
For updating multiple rows in a single query, you can try this
UPDATE table_name
SET
column_1 = CASE WHEN any_column = value and any_column = value THEN column_1_value end,
column_2 = CASE WHEN any_column = value and any_column = value THEN column_2_value end,
column_3 = CASE WHEN any_column = value and any_column = value THEN column_3_value end,
.
.
.
column_n = CASE WHEN any_column = value and any_column = value THEN column_n_value end
if you don't need additional condition then remove and part of this query
Let's say you have an array of IDs and equivalent array of statuses - here is an example how to do this with a static SQL (a sql query that doesn't change due to different values) of the arrays :
drop table if exists results_dummy;
create table results_dummy (id int, status text, created_at timestamp default now(), updated_at timestamp default now());
-- populate table with dummy rows
insert into results_dummy
(id, status)
select unnest(array[1,2,3,4,5]::int[]) as id, unnest(array['a','b','c','d','e']::text[]) as status;
select * from results_dummy;
-- THE update of multiple rows with/by different values
update results_dummy as rd
set status=new.status, updated_at=now()
from (select unnest(array[1,2,5]::int[]) as id,unnest(array['a`','b`','e`']::text[]) as status) as new
where rd.id=new.id;
select * from results_dummy;
-- in code using **IDs** as first bind variable and **statuses** as the second bind variable:
update results_dummy as rd
set status=new.status, updated_at=now()
from (select unnest(:1::int[]) as id,unnest(:2::text[]) as status) as new
where rd.id=new.id;
Came across similar scenario and the CASE expression was useful to me.
UPDATE reports SET is_default =
case
when report_id = 123 then true
when report_id != 123 then false
end
WHERE account_id = 321;
Reports - is a table here, account_id is same for the report_ids mentioned above. The above query will set 1 record (the one which matches the condition) to true and all the non-matching ones to false.
The answer provided by #zero323 works great on Postgre 12. In case, someone has multiple values for column_b (referred in OP's question)
UPDATE conupdate SET orientation_status = CASE
when id in (66934, 39) then 66
when id in (66938, 49) then 77
END
WHERE id IN (66934, 39, 66938, 49)
In the above query, id is analogous to column_b; orientation_status is analogous to column_a of the question.
In addition to other answers, comments and documentation, the datatype cast can be placed on usage. This allows an easier copypasting:
update test as t set
column_a = c.column_a::number
from (values
('123', 1),
('345', 2)
) as c(column_b, column_a)
where t.column_b = c.column_b::text;
#Roman thank you for the solution, for anyone using node, I made this utility method to pump out a query string to update n columns with n records.
Sadly it only handles n records with the same columns so the recordRows param is pretty strict.
const payload = {
rows: [
{
id: 1,
ext_id: 3
},
{
id: 2,
ext_id: 3
},
{
id: 3,
ext_id: 3
} ,
{
id: 4,
ext_id: 3
}
]
};
var result = updateMultiple('t', payload);
console.log(result);
/*
qstring returned is:
UPDATE t AS t SET id = c.id, ext_id = c.ext_id FROM (VALUES (1,3),(2,3),(3,3),(4,3)) AS c(id,ext_id) WHERE c.id = t.id
*/
function updateMultiple(table, recordRows){
var valueSets = new Array();
var cSet = new Set();
var columns = new Array();
for (const [key, value] of Object.entries(recordRows.rows)) {
var groupArray = new Array();
for ( const [key2, value2] of Object.entries(recordRows.rows[key])){
if(!cSet.has(key2)){
cSet.add(`${key2}`);
columns.push(key2);
}
groupArray.push(`${value2}`);
}
valueSets.push(`(${groupArray.toString()})`);
}
var valueSetsString = valueSets.join();
var setMappings = new String();
for(var i = 0; i < columns.length; i++){
var fieldSet = columns[i];
setMappings += `${fieldSet} = c.${fieldSet}`;
if(i < columns.length -1){
setMappings += ', ';
}
}
var qstring = `UPDATE ${table} AS t SET ${setMappings} FROM (VALUES ${valueSetsString}) AS c(${columns}) WHERE c.id = t.id`;
return qstring;
}
I don't think the accepted answer is entirely correct. It is order dependent. Here is an example that will not work correctly with an approach from the answer.
create table xxx (
id varchar(64),
is_enabled boolean
);
insert into xxx (id, is_enabled) values ('1',true);
insert into xxx (id, is_enabled) values ('2',true);
insert into xxx (id, is_enabled) values ('3',true);
UPDATE public.xxx AS pns
SET is_enabled = u.is_enabled
FROM (
VALUES
(
'3',
false
,
'1',
true
,
'2',
false
)
) AS u(id, is_enabled)
WHERE u.id = pns.id;
select * from xxx;
So the question still stands, is there a way to do it in an order independent way?
---- after trying a few things this seems to be order independent
UPDATE public.xxx AS pns
SET is_enabled = u.is_enabled
FROM (
SELECT '3' as id, false as is_enabled UNION
SELECT '1' as id, true as is_enabled UNION
SELECT '2' as id, false as is_enabled
) as u
WHERE u.id = pns.id;
I'm facing an issue to select the value from the same object. I provided the query below.
I'm migrating a Java J2EE application to Salesforce, the below query works in my SQL.
I'm trying to do the same in SOQL, but it doesn't work.
SELECT DATA1__c, TEXT__c
FROM PARAMETERS__c
WHERE ( (TYPE__c = 'ADMINISTRATEUR')
AND (KEY1__c LIKE 'MONTAGE%') (AND KEY2__c = ''))
AND (DATA1__c
IN (SELECT KEY1__c
FROM Parameters__c
WHERE TYPE__c = 'PERE_TECHNIQUE'))
In the above query I need to take the value where TYPE is based on 'TECHNIQUE' where KEY1__c should be matched to DATA1__c from the outer query.
The query is very similar to this example
SELECT Id
FROM Idea
WHERE ((Idea.Title LIKE 'Vacation%')
AND (CreatedDate > YESTERDAY)
AND (Id IN (SELECT ParentId
FROM Vote
WHERE CreatedById = '005x0000000sMgYAAU'))
The only difference is that IN clause is used with a different object.
In my query I'm trying to use IN clause from the same object parameters.
Kindly let me know in case of any further clarifications.
try the following
List<String> pereTechniqueParams = new List<String>();
for (String key:
[SELECT KEY1__c FROM Parameters__c WHERE TYPE__c = 'PERE_TECHNIQUE']) {
pereTechniqueParams.add(key.KEY1__c);
}
List<Parameters__c> params = [SELECT DATA1__c, TEXT__c
FROM PARAMETERS__c
WHERE (TYPE__c = 'ADMINISTRATEUR'
AND KEY1__c LIKE 'MONTAGE%'
AND KEY2__c = '')
AND DATA1__c IN:pereTechniqueParams];
UPDATE:
for (Parameters__c key1 : [SELECT KEY1__c
FROM Parameters__c WHERE TYPE__c = 'PERE_TECHNIQUE']) {
pereTechniqueParams.add(key1.KEY1__c);
}
Don't use String use Parameters__c
public class LookUpController {
public List<Parameters__c> getParamters() {
List<String> pereTechniqueParams = new List<String>();
for (Parameters__c key1 : [SELECT KEY1__c
FROM Parameters__c WHERE TYPE__c = 'PERE_TECHNIQUE']) {
pereTechniqueParams.add(key1.KEY1__c);
}
List<Parameters__c> params = [SELECT DATA1__c, TEXT__c
FROM PARAMETERS__c
WHERE TYPE__c = 'ADMINISTRATEUR'
AND KEY1__c LIKE 'MONTAGE%'
AND KEY2__c = ''
AND Data1__c IN: pereTechniqueParams];
return params;
}
}
The Vote Id and Idea Id is not same, The inner selection return list of Vote, And there is not result for sub-query Id IN (SELECT ParentId FROM Vote....
Channge Code To
set<Id> ideaIdSet = new set<Id>();
for(Vote vote : [SELECT ParentId FROM Vote WHERE CreatedById = '005x0000000sMgYAAU']){
ideaIdSet.add(vote.ParentId);
}
SELECT Id
FROM Idea
WHERE ((Title LIKE 'Vacation%')
AND (CreatedDate > YESTERDAY)
AND (Id IN ideaIdSet)
I'm trying to get latest inserted id from a table using this code:
$id = $tbl->fetchAll (array('public=1'), 'id desc');
but it's always returning "1"
any ideas?
update: I've just discovered toArray();, which retrieves all the data from fetchAll. The problem is, I only need the ID. My current code looks like this:
$rowsetArray = $id->toArray();
$rowCount = 1;
foreach ($rowsetArray as $rowArray) {
foreach ($rowArray as $column => $value) {
if ($column="id") {$myid[$brr] = $value;}
//echo"\n$myid[$brr]";
}
++$rowCount;
++$brr;
}
Obviously, I've got the if ($column="id") {$myid[$brr] = $value;} thing wrong.
Can anyone point me in the right direction?
An aternative would be to filter ID's from fetchAll. Is that possible?
Think you can use:
$id = $tbl->lastInsertId();
Aren't you trying to get last INSERT id from SELECT query?
Use lastInsertId() or the value returned by insert: $id = $db->insert();
Why are you using fetchAll() to retrieve the last inserted ID? fetchAll() will return a rowset of results (multiple records) as an object (not an array, but can be converted into an array using the toArray() method). However, if you are trying to reuse a rowset you already have, and you know the last record is the first record in the rowset, you can do this:
$select = $table->select()
->where('public = 1')
->order('id DESC');
$rows = $table->fetchAll($select);
$firstRow = $rows->current();
$lastId = $firstRow->id;
If you were to use fetchRow(), it would return a single row, so you wouldn't have to call current() on the result:
$select = $table->select()
->where('public = 1')
->order('id DESC');
$row = $table->fetchRow($select);
$lastId = $row->id;
It sounds like it's returning true rather than the actual value. Check the return value for the function fetchAll
I've got a MySQL database with typical schema for tagging items:
item (1->N) item_tag (N->1) tag
Each tag has a name and a count of how many items have that tag
ie:
item
(
item_id (UNIQUE KEY)
)
item_tag
(
item_id (NON-UNIQUE INDEXED),
tag_id (NON-UNIQUE INDEXED)
)
tag
(
tag_id (UNIQUE KEY)
name
count
)
I need to write a maintenance routine to batch re-tag one or more existing tags to a single new or existing other tag. I need to make sure that after the retag, no items have duplicate tags and I need to update the counts on each tag record to reflect the number of actual items using that tag.
Looking for suggestions on how to implement this efficiently...
if i understood you correctly then you could try something like this:
/* new tag/item table clustered PK optimised for group by tag_id
or tag_id = ? queries !! */
drop table if exists tag_item;
create table tag_item
(
tag_id smallint unsigned not null,
item_id int unsigned not null,
primary key (tag_id, item_id), -- clustered PK innodb only
key (item_id)
)
engine=innodb;
-- populate new table with distinct tag/items
insert ignore into tag_item
select tag_id, item_id from item_tag order by tag_id, item_id;
-- update counters
update tag inner join
(
select
tag_id,
count(*) as counter
from
tag_item
group by
tag_id
) c on tag.tag_id = c.tag_id
set
tag.counter = c.counter;
An index/constraint on the item_tag table can prevent duplicate tags; or create the table with a composite primary key using both item_id and tag_id.
As to the counts, drop the count column from the tag table and create a VIEW to get the results:
CREATE VIEW tag_counts AS SELECT tag_id, name, COUNT(*) AS count GROUP BY tag_id, name
Then your count is always up to date.
This is what I've got so far, which seems to work but I don't have enough data yet to know how well it performs. Comments welcome.
Some notes:
Had to add a unique id field to to the item_tags table get the duplicate tag cleanup working.
Added support for tag aliases so that there's a record of retagged tags.
I didn't mention this before but each item also has a published flag and only published items should affect the count field on tags.
The code uses C#, subsonic+linq + "coding horror", but is fairly self explanatory.
The code:
public static void Retag(string new_tag, List<string> old_tags)
{
// Check new tag name is valid
if (!Utils.IsValidTag(new_tag))
{
throw new RuleException("NewTag", string.Format("Invalid tag name - {0}", new_tag));
}
// Start a transaction
using (var scope = new SimpleTransactionScope(megDB.GetInstance().Provider))
{
// Get the new tag
var newTag = tag.SingleOrDefault(x => x.name == new_tag);
// If the new tag is an alias, remap to the alias instead
if (newTag != null && newTag.alias != null)
{
newTag = tag.SingleOrDefault(x => x.tag_id == newTag.alias.Value);
}
// Get the old tags
var oldTags = new List<tag>();
foreach (var old_tag in old_tags)
{
// Ignore same tag
if (string.Compare(old_tag, new_tag, true)==0)
continue;
var oldTag = tag.SingleOrDefault(x => x.name == old_tag);
if (oldTag != null)
oldTags.Add(oldTag);
}
// Redundant?
if (oldTags.Count == 0)
return;
// Simple rename?
if (oldTags.Count == 1 && newTag == null)
{
oldTags[0].name = new_tag;
oldTags[0].Save();
scope.Complete();
return;
}
// Create new tag?
if (newTag == null)
{
newTag = new tag();
newTag.name = new_tag;
newTag.Save();
}
// Build a comma separated list of old tag id's for use in sql 'IN' clause
var sql_old_tags = string.Join(",", (from t in oldTags select t.tag_id.ToString()).ToArray());
// Step 1 - Retag, allowing duplicates for now
var sql = #"
UPDATE item_tags
SET tag_id=#newtagid
WHERE tag_id IN (" + sql_old_tags + #");
";
// Step 2 - Delete the duplicates
sql += #"
DELETE t1
FROM item_tags t1, item_tags t2
WHERE t1.tag_id=t2.tag_id
AND t1.item_id=t2.item_id
AND t1.item_tag_id > t2.item_tag_id;
";
// Step 3 - Update the use count of the destination tag
sql += #"
UPDATE tags
SET tags.count=
(
SELECT COUNT(items.item_id)
FROM items
INNER JOIN item_tags ON item_tags.item_id = items.item_id
WHERE items.published=1 AND item_tags.tag_id=#newtagid
)
WHERE
tag_id=#newtagid;
";
// Step 4 - Zero the use counts of the old tags and alias the old tag to the new tag
sql += #"
UPDATE tags
SET tags.count=0,
alias=#newtagid
WHERE tag_id IN (" + sql_old_tags + #");
";
// Do it!
megDB.CodingHorror(sql, newTag.tag_id, newTag.tag_id, newTag.tag_id, newTag.tag_id).Execute();
scope.Complete();
}