First question ever on here, and pretty new to coding full apps/Rails.
I was creating a method to get the counts for titles by author, and noticed that if the author is cased differently, it would count as different authors. I wanted to place some sort of validation/check to disregard the casing and count it together. I don't care about the casing of the book titles in this particular case.
So I have table like this:
Author Book Title Year Condition
William Shakespeare Hamlet 1599 Poor
Stephen King The Shining 1977 New
Edgar Allen Poe The Raven 1845 Good
JK Rowling Harry Potter and the Sorcerer's Stone 2001 New
edgar allen poe The Tell-Tale Heart 1843 Good
JK Rowling Fantastic Beasts and Where to Find Them 2001 New
I want to output this:
Author Count
William Shakespeare 1
Stephen King 1
Edgar Allen Poe 2
JK Rowling 2
My method was originally something like this:
def self.book_counts
distinct_counts = []
Book.group(:author).count.each do |count|
distinct_counts << count
end
distinct_counts
end
To ignore casing, I referenced this page and came up with these, which didn't end up working out, unfortunately:
1) With this one I get "undefined method lower":
Book.group(lower('author')).count.each do |count|
distinct_counts << count
2) This runs, but with the select method in general, I get a bunch of ActiveRecord results/Record id: nil. I am using Rails 6 and it additionally notes "DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s) ... Non-attribute arguments will be disallowed in Rails 6.1. This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql(). (called from irb_binding at (irb):579)":
Book.select("lower(author) as dc_auth, count(*) as book_count").group("dc_auth").order("book_count desc")
3) I even tried to test a different, simplified function to see if it'd work, but I got "ActiveRecord::StatementInvalid (PG::GroupingError: ERROR: column "books.author" must appear in the GROUP BY clause or be used in an aggregate function)":
Book.pluck('lower(author) as dc_auth, count(*) as book_count')
4) I've tried various other ways, with additional different errors, e.g. "undefined local variable or method 'dc_auth'", "undefined method 'group' did you mean group_by?", and "wrong number of arguments (given 1, expected 0)" (with group_by), etc.
This query works exactly how I want it to in postgresql. The syntax actually populates in the terminal when I run #2, but as mentioned, unfortunately due to ActiveRecord doesn't output properly in Rails.
SELECT lower(author) as dc_auth, count(*) as book_count FROM books GROUP BY dc_auth;
Is there even a way to run what I want through Rails??
Maybe you can try
Book.group("LOWER(author)").count
You can execute your query using ActiveRecord. And I will suggest to go with SQL block
book_count_query = <<-SQL
SELECT lower(author) as dc_auth, count(*) as book_count
FROM books
GROUP BY dc_auth;
SQL
1- result = ActiveRecord::Base.connection.execute(book_count_query)
or
2- result = ActiveRecord::Base.connection.exec_query(book_count_query)
What difference between line 1 and line 2?
exec_query it returns an ActiveRecords::Result object which has handy methods like .columns and .rows to access headers and values.
The array of hashes from .execute can be troublesome to deal with and gave me redundant results when I ran with a SUM GROUP BY clause.
If you need read more about this topic
example of exec_query in api.rubyonrails
active_record_querying in Rails Documentation
This Resource have example for query and output .
Why you store authors in the same table with books. The better solution is to add a separate table for authors and add a foreign key to author_id to books table. With counter_cache you can easily count the number of books for each author.
Here is a guide with books and authors examples https://guides.rubyonrails.org/association_basics.html
I want to get the one line printout by mix/merge different field value, like the following , (Mix or Merge is method what I assume)
select mix(value) from test group by “name”
name: test
tags: name=“case1”
time mix/merge
1970-01-01T00:00:00Z failed,passed,skipped
select * from test group by “name”
name: test
tags: name=“case1”
time caseAuthor caseName caseResult value
2018-07-20T03:51:42.599533888Z mike case1 pass 1
2018-07-20T03:51:42.690955475Z mike case1 failed 2
2018-07-20T03:51:42.723272883Z mike case1 skipped 3
thanks for any help
BRs
/Yijun
As for v1.6 there is no "join" or "concat" aggregation function in InfluxQL. All you can do is running
SELECT DISTINCT("caseResult")
FROM "test"
GROUP BY “name”
and then join values by "comma" separator in each group with some bash script or the programming language executing a query.
And actually, even though InfluxDB supports various data types (e.g. strings and booleans) InfluxQL support for processing data of types other then numeric is very-very poor in my opinion...
I'm trying to leverage my moderate SQL-knowledge for InfluxQL, but I'm missing something(s) about the nature of timeseries db.
Use case
I write a measurements from our issue tracker, when an issue is updated:
issue_updated,project=facebook,ticket=fb1,assignee=coolman status="todo"
Problem
Given this returns rows of issues statuses:
SELECT status
FROM "issue_updated"
If this was SQL (fiddle) I would use COUNT(and then add the WHERE time > NOW() - 1Y GROUP BY time(5m)). However the following gives me Mixing aggregate and non-aggregate queries is not supported
SELECT status, count(status) as 'Count'
FROM "issue_updated"
Can someone give some guidance here? ta
Sounds like what you're looking for is the ability to group by a field value which isn't currently supported.
From what I can tell, if you modify your schema a bit, it should be possible to do what you're looking. Instead of
issue_updated,project=facebook,ticket=fb1,assignee=coolman status="todo"
Do
issue_updated,project=facebook,ticket=fb1,assignee=coolman,status=todo value=1
then
SELECT count(value) FROM "issue_updated" WHERE time > now() - 52w GROUP BY status
name: issue_updated
tags: status=other
time count
---- -----
1449523659065350722 1
name: issue_updated
tags: status=todo
time count
---- -----
1449523659065350722 2
should work.
This:
- book.prices.order(:currency_code).each do |price|
returns all a book's prices ordered alphabetically by currency code:
AUD 19.99
GBP 9.99
NZD 26.00
USD 14.95
Now, how can I neatly get GBP to always appear at the top of the list, with the others sorting alphabetically, like this:
GBP 9.99
AUD 19.99
NZD 26.00
USD 14.95
This answer shows the SQL solution, but I'm not sure about the Rails way.
Since ordering is normally done on DB level, just use the SQL solution in rails:
- book.prices.order("`currency_code` = 'GBP' desc, currency_code").each do |price|
you can use sql snippets in Rails (ActiveRecord) query methods.
Depending on your DB you might have to choose the right SQL solutiuon, so probably
- book.prices.order("CASE WHEN currency_code = 'GBP' THEN 1 ELSE 2 END, currency_code").each do |price|
works in your case.
You can check the resulting sql in rails console:
book.prices.order("CASE WHEN currency_code = 'GBP' THEN 1 ELSE 2 END, currency_code").to_sql
and check, whether it works in you DB.
An other way is of cause to add an extra column for sorting, this way you can even position commonwelth currencies in front of others etc.
INFORMIX-SQL 7.3 Perform Screens:
According to documentation, in an "after editadd editupdate of table" control block, its instructions are executed before the row is added or updated to the table, whereas in an "after add update of table" control block, its instructions are executed after the row has been added or updated to the table. Supposedly, this would mean that any instructions which would alter values of field-tags linked to table.columns would not be committed to the table, but field-tags linked to displayonly fields will change?
However, when using "after add update of table", I placed instructions which alter values for field-tags linked to table.columns and their displayed and committed values also changed! I would have thought that an "after add update of table" would only alter displayonly fields.
TABLES
customer
transaction
branch
interest
dates
ATTRIBUTES
[...]
q = transaction.trx_type, INCLUDE=("E","C","V","P","T"), ...;
tb = transaction.trx_int_table,
LOOKUP f1 = ta_days1_f,
t1 = ta_days1_t,
i1 = ta_int1,
[...]
JOINING *interest.int_table, ...;
[...]
INSTRUCTIONS
customer MASTER OF transaction
transaction MASTER OF customer
delimiters ". ";
AFTER QUERY DISPLAY ADD UPDATE OF transaction
if z = "E" then let q = "E"
if z = "C" then let q = "C"
if z = "1" then let q = "E"
[...]
END
Is 'z' a column in the transaction table?
Is the trouble that the value in 'z' is causing a change in the value of 'q' (aka transaction.trx_type), and the modified value is being stored in the database?
Is the value in 'z' part of the transaction table?
Have you verified that the value in the DB is indeed changed - using the Query Language option or a simple (default) form?
It might look as if it is because the instruction is also used AFTER DISPLAY, so when the values are retrieved from the DB, the value displayed in 'q' would be the mapped values corresponding to the value stored in 'z'. You would have to inspect the raw data to hide that mapping.
If this is not the problem, please:
Amend the question to show where 'z' comes from.
Also describe exactly what you do and see.
Confirm that the data in the database, as opposed to on the screen, is amended.
Please can you see whether this table plus form behaves the same for you as it does for me?
Table Transaction
CREATE TABLE TRANSACTION
(
trx_id SERIAL NOT NULL,
trx_type CHAR(1) NOT NULL,
trx_last_type CHAR(1) NOT NULL,
trx_int_table INTEGER NOT NULL
);
Form
DATABASE stores
SCREEN SIZE 24 BY 80
{
trx_id [f000]
trx_type [q]
trx_last_type [z]
trx_int_table [f001 ]
}
END
TABLES
transaction
ATTRIBUTES
f000 = transaction.trx_id;
q = transaction.trx_type, UPSHIFT, AUTONEXT,
INCLUDE=("E","C","V","P","T");
z = transaction.trx_last_type, UPSHIFT, AUTONEXT,
INCLUDE=("E","C","V","P","T","1");
f001 = transaction.trx_int_table;
INSTRUCTIONS
AFTER ADD UPDATE DISPLAY QUERY OF transaction
IF z = "E" THEN LET q = "E"
IF z = "C" THEN LET q = "C"
IF z = "1" THEN LET q = "E"
END
Experiments
[The parenthesized number is automatically generated by IDS/Perform.]
Add a row with data (1), V, E, 23.
Observe that the display is: 1, E, E, 23.
Exit the form.
Observe that the data in the table is: 1, V, E, 23.
Reenter the form and query the data.
Update the data to: (1), T, T, 37.
Observe that the display is: 1, T, T, 37.
Exit the form.
Observe that the data in the table is: 1, T, T, 37.
Reenter the form and query the data.
Update the data to: (1), P, 1, 49
Observe that the display is: 1, E, 1, 49.
Exit the form.
Observe that the data in the table is: 1, P, 1, 49.
Reenter the form and query the data.
Observe that the display is: 1, E, 1, 49.
Choose 'Update', and observe that the display changes to: 1, P, 1, 49.
I did the 'Observe that the data in the table is' steps using:
sqlcmd -d stores -e 'select * from transaction'
This generated lines like these (reflecting different runs):
1|V|E|23
1|P|1|49
That is my SQLCMD program, not Microsoft's upstart of the same name. You can do more or less the same thing with DB-Access, except it is noisier (13 extraneous lines of output) and you would be best off writing the SELECT statement in a file and providing that as an argument:
$ echo "select * from transaction" > check.sql
$ dbaccess stores check
Database selected.
trx_id trx_type trx_last_type trx_int_table
1 P 1 49
1 row(s) retrieved.
Database closed.
$
Conclusions
This is what I observed on Solaris 10 (SPARC) using ISQL 7.50.FC1; it matches what the manual describes, and is also what I suggested in the original part of the answer might be the trouble - what you see on the form is not what is in the database (because of the INSTRUCTIONS section).
Do you see something different? If so, then there could be a bug in ISQL that has been fixed since. Technically, ISQL 7.30 is out of support, I believe. Can you upgrade to a more recent version than that? (I'm not sure whether 7.32 is still supported, but you should really upgrade to 7.50; the current release is 7.50.FC4.)
Transcribing commentary before deleting it:
Up to a point, it is good that you replicate my results. The bad news is that in the bigger form we have different behaviour. I hope that ISQL validates all limits - things like number of columns etc. However, there is a chance that they are not properly validated, given the bug, or maybe there is a separate problem that only shows with the larger form. So, you need to ensure you have a supported version of the product and that the problem reproduces in it. Ideally, you will have a smaller version of the table (or, at least, of the form) that shows the problem, and maybe a still smaller (but not quite as small as my example) version that shows the absence of the problem.
With the test case (table schema and Perform screen that shows the problem) in hand, you can then go to IBM Tech Support with "Look - this works correctly when the form is small; and look, it works incorrectly when the form is large". The bug should then be trackable. You will need to include instructions on how to reproduce the bug similar to those I gave you. And there is no problem with running two forms - one simple and one more complex and displaying the bug - in parallel to show how the data is stored vs displayed. You could describe the steps in terms of 'Form A' and 'Form B', with Form A being Absolutely OK and Form B being Believed to be Buggy. So, add a record with certain values in Form B; show what is displayed in Form B after; show what is stored in the database in Form A after too; show that they are not different when they should be.
Please bear in mind that those who will be fixing the issue have less experience with the product than either you or me - so keep it as simple as possible. Remove as many attributes as you can; leave comments to identify data types etc.