Get original view definition from POSTGRESQL DB - view

I have created a view with the below definition :
CREATE TABLE t1(id int,name varchar);
INSERT INTO t1 values(1,'n1'),(2,'n2');
CREATE VIEW v2 AS SELECT * FROM t1 WHERE name = 'n1';
But when i checked the definition in postgresql DB(9.5) in pg_views table, it is getting modified in the below way :
postgres=# select * from pg_views where schemaname = 'sc1' and viewname = 'v2';
schemaname | viewname | viewowner | definition
------------+----------+-----------+-----------------------------------------
sc1 | v2 | postgres | SELECT t1.id, +
| | | t1.name +
| | | FROM sc1.t1 +
| | | WHERE ((t1.name)::text = 'n1'::text);
(1 row)
I am fine with adding tablename before columnname but i don't want the extra '::text' part.
Is there anyway to achieve this(like any other system table i can query from to get original definition)

You can not get the "original" view definition from the Postgres system tables.
Postgres only stores the parsed version.

Related

How to select based on child of child relationship using Laravel Eloquent?

I have the following tables structure for merchants & dynamic filters
Merchant Table
id | name
-------------------------
1 | Food Supplier
Filters
id | name
-------------------------
1 | Service Area
2 | Service Cost
Filter Values
id | filter_id | value
-------------------------
1 | 1 | Africa
2 | 1 | Europe
3 | 2 | 2000-4000
4 | 2 | 4000-6000
Merchant Filter Values
id | filter_id | value_id | merchant_id
----------------------------------------
1 | 1 | 1 | 1
2 | 1 | 2 | 1
3 | 2 | 4 | 1
I run the following query to search through merchants using filters:
select *
from `merchants`
where `name` LIKE "%search_term%"
and exists (
select *
from `filter_values`
inner join `merchant_filter_values`
on `filter_values`.`id` = `merchant_filter_values`.`value_id`
where `merchants`.`id` = `merchant_filter_values`.`merchant_id`
and (`filter_values`.`id` = 1 and filter_values.filter_id = 2)
or (`filter_values`.`id` = 2 and filter_values.filter_id = 3)
or etc.
)
The query works fine, and returns results as expected, the only problem that it is not eloquent so it doesn't return appends variables/functions from the model for example that featured_img_url is not returned in the result:
protected $appends = array('featured_img_url');
public function getFeaturedImgUrlAttribute()
{
$img_path = Config::get('app.asset_url') . "/merchants/featured/" . $this->id . ".";
return $img_path . $this->featured_image_ext . $this->getLastUpdatedUrl();
}
The question is, how do I write such query using laravel eloquent?
You have to use hydrate() function to convert result of select query to eloquent collection. you can use something like this:
$merchants = \DB::select( "select *
from `merchants`
where `name` LIKE '%search_term%'
and exists (
select *
from `filter_values`
inner join `merchant_filter_values`
on `filter_values`.`id` = `merchant_filter_values`.`value_id`
where `merchants`.`id` = `merchant_filter_values`.`merchant_id`
and (`filter_values`.`id` = 1 and filter_values.filter_id = 2)
or (`filter_values`.`id` = 2 and filter_values.filter_id = 3)
or etc.
)" );
return Merchant::hydrate($merchants);
You have to define Merchant Model too.

How to pass multiple values to UPDATE or SELECT COUNT(*) statement

I am trying to do a update a record.
Table name is customer
id | name | address | state
---+---------+------------+-------------------------
1 | John | 123 main st | TX
2 | Jack | 678 John st | NJ
3 | Bet | 987 Tx st | NY
4 | Maddy| 9812 Hudson st | CA
5 | ABCD | 9813 Mainly st | PA
My query is like below
UPDATE CUSTOMER c SET c.state = 'CA' WHERE c.id IN (idList);
Where idList is a localVariable that I created and it returns a list of id like 1,3,5
The query is working if do it like
UPDATE CUSTOMER c SET c.state = 'CA' WHERE c.id IN (1,3,5);
It is updating the respective records to CA.
But if I use it as
UPDATE CUSTOMER c SET c.state = 'CA' WHERE c.id IN (idList);
I get the below error. I don't want to pass the list directly as the list might change. I am getting the list of ids using a different command where it returns and assigns to idList as 1,3,5
Error:
ORA-01722: invalid number
ORA-06512: at line 35
01722. 00000 - "invalid number"**
How to solve this? I am writing it as a stored procedure.
I guess idList is a comma separated string with all the ids that you want to update.So what is happening is that the operator IN compares each id with that string and since this comparison can't succeed in any case you get an error.
What you can do instead is use the LIKE operator:
UPDATE customer
SET "state" = 'CA'
WHERE ',' || idList || ',' LIKE '%,' || "id" || ',%'
See the demo.
You may create parameterized query string and pass values like,
UPDATE CUSTOMER c SET c.state = 'CA' WHERE c.id IN (:idList);
You can't substitute a text variable for a list of values - it's simply not allowed. You're going to have to use dynamic SQL:
EXECUTE IMMEDIATE 'UPDATE CUSTOMER c SET c.state = ''CA'' WHERE c.id IN (' || idList || ')';

How do I query array element in impala?

I created a table in impala ,the have two columns ,
+-----------+---------------------+---------+
| name | type | comment |
+-----------+---------------------+---------+
| unique_id | string | |
| cmap | array<struct< | |
| | fieldname:string, | |
| | fieldid:string, | |
| | fielddata:string | |
| | >> | |
+-----------+---------------------+---------+
i need set the conditions for cmap to query unique_id, such as
(fieldname="ip"and fielddata="192.168.1.145") and(fieldname="wid" and fielddata="15")
i wrote this sql but can't query it, but i inserted the data in the table
sql:
select unique_id from s_click_parquet,s_click_parquet.cmap as lst where ( fieldname="ip" and fieldData="192.168.1.145") and(fieldname="wid" and fielddata="15");
You typically access arrays with square brackets, but you can have an array of structs, not just an array.
You can INLINE() an array of struct to make it multiple rows, as well as splitting the fields to queryable columns.
Then you can query it as you would a normal table.
Play around with
select *
from table1 t
lateral view inline(cmap) a;
From my work collogue:
so rule of thumb is structs can get accessed via strucName., while arrays have to be joined*
So if we have the following types from an avro schema:
case class Visit (var Patient: PatientType = null)
case class PatientType(
var Name: String = null,
var Address: List[AddressType] = null
)
case class AddressType(
var Line1: String = null,
var Line2: String = null,
var City: String = null,
var State: String = null,
var ZipCode: String = null
)
You would query for patient name and address like:
select vis.patient.name, addr.item.*
from visit vis
left join vis.patient.address addr

Distinct query in Criteria NHibernate

I need the corresponding query in Criteria language to this one (to retrieve all categories from my table but to distinct them):
SELECT DISTINCT categoryName
FROM Category
WHERE CategoryID IN (
SELECT CategoryID
FROM FoodCategory
)
ORDER BY categoryName
I have table FoodCategory table
id | FoodID | CategoryID
--------|---------------|------------
| |
| |
| |
Actually CategoryID is a foreign key that is pointing to this table here. This is table for Category:
CategoryID | categoryName | otherField
---------------|------------------|------------
| |
| |
| |
And this is table for Food:
FoodID | FoodName | otherField
---------------|------------------|------------
| |
| |
| |
Something like that should do the trick :
public List<String> retrieveFoodCategoryNames() {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<String> criteriaQuery = builder.createQuery(String.class);
Root<FoodCategory> root = criteriaQuery.from(FoodCategory.class);
// by default an inner join so it will only get the categories which have their id in the FoodCategory table
Join<FoodCategory, Category> joinCategory = root.join(FoodCategory_.category);
Fetch<FoodCategory, Category> fetchCategory = root.fetch(FoodCategory_.category);
Path<String> categoryNamePath = fetchCategory.get(Category_.categoryName);
criteriaQuery.select(categoryNamePath).distinct(true);
criteriaQuery.orderBy(builder.asc(categoryNamePath));
return entityManager.createQuery(criteriaQuery).getResultList();
}
This is not the exact same SQL request because you used a subquery where I'm using a join but it seemed more suited to this particular case. The subquery syntax is a bit more complex and I will not try to write it without compiling! ^^
If something is unclear let me know :-)

Select nested list

I have three tables in DB like this:
products
+----+------+
| id | name |
+----+------+
| 1 | prod1|
+----+------+
values
+----+---------+---------+
| id | value | alias |
+----+---------+---------+
| 1 | 10 g | 10m |
+----+---------+---------+
prdoucts_values
+---------------+---------+
| product_id | value_id|
+---------------+---------+
| 1 | 1 |
+---------------+---------+
How select all products from DB, that have any value from List<Values.alias> ?
List<decimal> aliases = ...
var query = db.Products.Where(p => p.Values.Any(v => aliases.Contains(v.Alias)));
Or (if you don't have navigation properties)
var query = from p in db.Products
join pv in db.ProductsValues on p.ProductId equals v.ProductId
join v in db.Values on pv.ValueId equals v.ValueId into values
where values.Any(v => aliases.Contains(v.Alias))
select p
If you are using EF (database first) then the table prdoucts_values is not part of the conseptual model.
instead EF givs you a direct path from Products to Values
Therefore you can write a query that look like this:
var lst = new List<Products>();
lst = db.Products.Where(c => c.Values.Any()).ToList();

Resources