How do I store array of integers in vertica database? - mysql

Currently I'm working on vertica database.
I'm facing problem while storing array of integers in one column. I imported data values through csv.
I used the following code to create table.
CREATE TABLE testing_table_1 (email varchar,name varchar,gen int,yob int,ct int,cy int,a varchar(65000),b varchar(65000),c varchar(65000));
I imported data with the following code.
COPY testing_table_1 from '/home/naresh/Desktop/bigfile.csv' parser fcsvparser();
My sample CSV format looks like the below.
ghchnu#tly.org.cn | Donald Garcia | 2 | 2003 | 21947 | 91 | 241,127,225,68,162 | 4,84,63,69,15 | 32,44,15,31
rlmx#jyqewy.biz | Charles Brown | 2 | 2012 | 22218 | 45 | 127,156,186,136,242 | 49,69,14,80,95,1 | 39,36,38,40,20
7th,8th and 9th columns are storing in the format of a string.
But what I want is, I want them to be stored in an array of integers format.
Because of the string format I am unable to perform combination of integers operation using 'IN' query.
I don't to want to use flex-table format in vertica.
Give suggestions other than flex-table format.
Please give me a possible solution for the above problem.
Please correct me if I am doing any mistake.
Thanks in advance,

Vertica is a real, SQL based, relational database.
And those actually do not have rows with a variable number of columns - which is what using arrays would boil down to.
What you need to do is to make, out of this:
[...] 91 | 241,127,225,68,162 | 4,84,63,69,15 | 32,44,15,31
This:
[...] 91 | 1 | 241 | 4 | 32
[...] 91 | 2 | 127 | 84 | 44
[...] 91 | 3 | 225 | 63 | 15
[...] 91 | 4 | 68 | 69 | 31
[...] 91 | 5 | 162 | 15 |(null)
Check out the SPLIT_PART() function; you might want to run it with 1,2,3,4 and finally 5 as the third parameter, and use that very number as the key that you see in the second displayed column above. To get the resulting column as integers, cast the strings that come out of the SPLIT_PART() function to integers.
Good luck -
Marco

Related

Mysql - XML like table with multiple values in same column

My question title is confusing, sorry about that.
I have one application that saves data in the database in XML'ish format, referencing keys and values.
The problem is that I have only one column with several values that corresponds to a certain key.
I need to have certain keys as columns but I am failing miserably to achieve that:
Below a sample of the table I have
xml_type | xml_key | xml_content_key | xml_content_value
----------------------------------------------------------------------------------------------------
Archiv::144 | 144 | [1]{'Version'}[1]{'Carrier'}[1]{'Content'} | 151
Archiv::144 | 144 | [1]{'Version'}[1]{'CarrierID'}[1]{'Content'} | 5714141614
Archiv::144 | 144 | [1]{'Version'}[1]{'CustomerInterface'}[1]{'Content'} | 145
So, I can run this and have all the carriers:
select xml_content_key as Carrier, xml_content_value as 'Carrier Result'
from xml_storage xs where xml_content_key LIKE '%[1]{\'Version\'}[1]{\'Carrier\'}[1]{\'Content\'}%'
But how would I other keys from column xml_content_key to be shown as coluns.
I have tried nested selects but got "Returns more than one value", a join would not apply since this is on a single table.
In short, I would like to run a query to gather a few keys from column xml_content_key and have each in a new column.
Thank you.
Without knowing the schema of either your table or your XML document I'll have to make some assumptions. But I think this isn't too hard. First I'll write out the assumptions I'm making. Please correct me if these assumptions are wrong.
It seems like you have a table in which xml_content_key is what should be the column name, and xml_key is what should be the row identifier. You only showed a very limited sample in your question, but my assumption would suggest that more data might look like this.
xml_type | xml_key | xml_content_key | xml_content_value
----------------------------------------------------------------------------------------------------
Archiv::144 | 144 | [1]{'Version'}[1]{'Carrier'}[1]{'Content'} | 151
Archiv::144 | 144 | [1]{'Version'}[1]{'CarrierID'}[1]{'Content'} | 5714141614
Archiv::144 | 144 | [1]{'Version'}[1]{'CustomerInterface'}[1]{'Content'} | 145
Archiv::144 | 145 | [1]{'Version'}[1]{'Carrier'}[1]{'Content'} | 123
Archiv::144 | 145 | [1]{'Version'}[1]{'CarrierID'}[1]{'Content'} | 4567891234
Archiv::144 | 145 | [1]{'Version'}[1]{'CustomerInterface'}[1]{'Content'} | 567
Archiv::144 | 146 | [1]{'Version'}[1]{'Carrier'}[1]{'Content'} | 891
Archiv::144 | 146 | [1]{'Version'}[1]{'CarrierID'}[1]{'Content'} | 2345678912
Archiv::144 | 146 | [1]{'Version'}[1]{'CustomerInterface'}[1]{'Content'} | 345
And I think you're trying to write a query to reorganize it like this.
+---------+---------+------------+-------------------+
| xml_key | Carrier | CarrierID | CustomerInterface |
+---------+---------+------------+-------------------+
| 144 | 151 | 5714141614 | 145 |
| 145 | 123 | 4567891234 | 567 |
| 146 | 891 | 2345678912 | 345 |
+---------+---------+------------+-------------------+
If I'm wrong about this part then there's no point in reading on. But if I'm right so far, then I'd like to highlight a quote from your question.
a join would not apply since this is on a single table.
You have been missing out on a great feature of SQL: self joins are extremely useful in cases like this.
It appears that there are three "content keys" (or columns) for each xml_key (or row). We will join together all the xml_content_key's that share the same xml_key, so that each row will describe a single xml_key. By the way, I'm assuming your table is named xml_storage.
SELECT xs1.xml_key AS 'xml_key',
xs1.xml_content_value AS 'Carrier',
xs2.xml_content_value AS 'CarrierID',
xs3.xml_content_value AS 'CustomerInterface'
FROM xml_storage xs1
INNER JOIN xml_storage xs2 ON xs2.xml_key = xs1.xml_key
INNER JOIN xml_storage xs3 ON xs3.xml_key = xs1.xml_key
WHERE xs1.xml_content_key LIKE "%[1]{'Version'}[1]{'Carrier'}[1]{'Content'}%"
AND xs2.xml_content_key LIKE "%[1]{'Version'}[1]{'CarrierID'}[1]{'Content'}%"
AND xs3.xml_content_key LIKE "%[1]{'Version'}[1]{'CustomerInterface'}[1]{'Content'}%"
The basic idea here is that we separate the table into three tables and then put them back together. We put the Carriers in xs1, the CarrierIDs in xs2, and the CustomerInterfaces in xs3. Then we join these back together, putting all of the content associated with a particular xml_key on the same row.
You will probably need to alter this to fit your actual schema. In particular, this query assumes that you have exactly one Carrier, CarrierID, and CustomerInterface per unique xml_key. I am confident that this general approach will work if your data is anything like I've been assuming, but imperfect data would necessitate a more robust query than the example I've given here.
If you can share more details about your particular schema, I would be happy to edit my suggested query to fit your situation.

Laravel get "unique" row from mysql

I have a special scenario to fetch "unique" row.
Let's say the database is like below
| id | userid | value | others |
|----|--------|-------|---------|
| 1 | 111 | 10 | string1 |
| 2 | 112 | 30 | string2 |
| 3 | 112 | 30 | string3 |
| 4 | 113 | 50 | string4 |
what I want to achieve is to fetch the unique rows based on the "userid" so I'am able to sum all values.
the expect output row can be either id: 1 2 4 or 1 3 4 (both is acceptable for this special case because same id guarantees same value, or in general, get just one row from those row with same userid. ), so the sum will be 90.
Note: DB is extended from Eloquent\model
My old approach is to get DB::unique('userid'); then for each userid DB::where('userid', $id)->value('value'), add the result to sum; I just believe there might be a better approach.
There is Illuminate\Support\Facades\DB in Laravel, it can return the Query Builder. Not recommend to use a model that is named DB.
So just change another name.
By the way, for Eloquent\Model, you can use groupBy and sum too:
Model::groupBy('user_id')->sum('value');

Parsing JSON Payload in Vertica

I am using Vertica DB (and DBeaver as SQL Editor) - I am new to both tools.
I have a view with multiple columns:
someint | xyz | c | json
5 | 1542 | none | {"range":23, "rm": 51, "spx": 30}
5 | 1442 | none | {"range":24, "rm": 50, "spx": 3 }
3 | 1462 | none | {"range":24, "rm": 50, "spx": 30}
(int) | (int) | (Varchar) | (Long Varchar)
I want to create another view (or for the beginning, just be able to query it properly) of the above, but with the "json" column separated into the individual fields/columns "range", "rm" and "spx".
I imagine the output of the query / the new view to be something like the following:
someint | xyz | c | range | rm | spx
5 | 1542 | none | 23 | 51 | 30
5 | 1442 | none | 24 | 50 | 3
....
So far I have not been able to even query the "range" for example.
Hence my questions:
How can I separate the json column key-value structure into individual columns (in a query output)?
How can I transfer the desired output into a new view in Vertica?
I haven't found much help in the documentation as the procedure there is to load json text files from a drive or operate on tables, which I cannot do as I only have access to a view.
I have found a solution, so for anyone else encountering this problem:
SELECT a, xyza, cont,
MAPLOOKUP(MapJSONExtractor(json), 'range') AS range,
MAPLOOKUP(MapJSONExtractor(json), 'rm') AS rm,
MAPLOOKUP(MapJSONExtractor(json), 'spx') AS spx
FROM test;

Round off values in 2 columns that have decimal places

Some of the value in two of my columns have decimal places for some reason, this is a bug in my code I need to sort out but its causing problems at the moment.
How can I round numbers with decimal places?
Example Data
# Table: level_3
|---------------------|
| day_start | day_end |
|-----------|---------|
| -123 | 20 |
| -650 | 234 |
| -133.042..| 104.0416|
| -581 | 123 |
|---------------------|
Expected Output
# Table: level_3
|---------------------|
| day_start | day_end |
|-----------|---------|
| -123 | 20 |
| -650 | 234 |
| -133 | 104 |
| -581 | 123 |
|---------------------|
EDIT: If it's any easier, it doesn't need to be rounded, just removed anything after and including the period.
EDIT 2: I have actually fixed my problem, I just changed the structure to INT and back which removed all the decimals! But thats for the answers, they will help others looking for this!
You have 2 simple options:
Round the values when you query the database, using ROUND, FLOOR, CEIL mysql function
e.g.:SELECT ROUND(day_start, 0) as day_start, ROUND(day_end, 0) as day_end
Round the value using php after you query the database, using round, floor or ceil
Use either the PHP floor() function, or the mysql FLOOR() function
PHP
<?php
echo floor(44.62); // will output "44"
MySQL
SELECT FLOOR(44.62);
-> 44
HOWEVER
SELECT FLOOR(-44.62);
-> -45
So, you can try something like:
SELECT IF(day_start < 0, CEIL(day_start), FLOOR(day_start)) s, IF(day_end < 0, CEIL(day_end), FLOOR(day_end)) e FROM level_3;
I'd suggest using either number_format or floor
You can try this (SQL Server)
SELECT CONVERT(INT,Day_Start), CONVERT(INT,Day_End)
SQL :
SELECT SUBSTRING (notetitle,1,4), SUBSTRING(notedescription,1,3) FROM notes
I have actually fixed my problem, I just changed the structure to INT and back which removed all the decimals! But thanks for the answers, they will help others looking for this!

MS Access: Any Ideas on How to Create an Excel-Like Form?

Objective: Convert an overgrown Excel sheet into an Access database, but maintain a front-end that is familiar and easy to use.
There are several aspects to this, but the one I'm stuck on is one of the input forms. I'm not going to clutter this question with the back-end implementation that I have already tried because I'm open to changing it. Currently, an Excel spreadsheet is used to input employee hour allocations to various tasks. It looks something like the following.
Employee | Task | 10/03/10 | 10/10/10 | 10/17/10 | 10/24/10 | ... | 12/26/11
---------------------------------------------------------------------------------
Doe, John | Code | 16 | 16 | 20 | 20 | ... | 40
---------------------------------------------------------------------------------
Smith, Jane | Code | 32 | 32 | 16 | 32 | ... | 32
---------------------------------------------------------------------------------
Doe, John | Test | 24 | 24 | 20 | 20 | ... | 0
---------------------------------------------------------------------------------
Smith, Jane | Test | 0 | 0 | 16 | 0 | ... | 0
---------------------------------------------------------------------------------
Smith, Jane | QA | 8 | 8 | 8 | 8 | ... | 8
---------------------------------------------------------------------------------
TOTAL | 80 | 80 | 80 | 80 | ... | 80
Note that there are fifteen months of data on the sheet and that employee allocations are entered for each week of those fifteen months. Currently, at the end of the fifteen months, a new sheet is created, but the database should maintain this data for historical purposes.
Does anyone have any ideas on how to create an editable form/datasheet that has the same look and feel? If not, how about an alternative solution that still provides the user a quick glance at all fifteen months and allows easy editing of the data? What would the back-end tables look like for your proposed solution?
This is a classic de-normalization problem.
To produce an editable spread-sheet like view of your database you'll need a table with 66 columns (the two identifying columns and 64 weekly integer columns). The question is whether you want the permanent storage of the data to use this table, or to use a normalized table with four columns (the two identifiers, the week-starting date, and the integer hours value).
I would give serious consideration to storing the data in the normalized form, then converting (using a temporary table) into the denormalized form, allowing the user to print/edit the data, and then converting back to normal form.
Using this technique you get the following benefits:
The ability to support rolling windows into the data (with 66 columns, you will see a specified 15 month period, and no other). With a rolling window you can show them last month and the next 14 months, or whatever.
It will be substantially easier to do things like check peoples total hours per month, or compare the hours spent in testing vs QA for an arbitrary range of dates.
Of course, you have to write the code to translate between normal and denormal form, but that should be pretty straightforward.