Вот мой код, как решить вышеуказанную проблему (при нажатии на ссылку запрашивается браузер по умолчанию, чтобы открыть ссылку)
import android.os.Bundle;import android.annotation.SuppressLint;import android.app.Activity;
import android.view.Menu;import android.webkit.WebChromeClient;
import android.webkit.WebView;public class MainActivity extends Activity{
`@SuppressLint("SetJavaScriptEnabled")@Override protected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);String url="http://google.com";WebView Webview=(WebView) this.findViewById(R.id.webView1); Webview.getSettings().setJavaScriptEnabled(true);Webview.loadUrl(url);}@Override public boolean onCreateOptionsMenu(Menu menu){//Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu);return true;}`}
Q: как получить псевдоним для использования в предложении GROUP BY
Один из подходов - использовать встроенное представление. [РЕДАКТИРОВАТЬ] Ответ от Ремуса Русану (+1! ) дает пример общего табличного выражения, выполняющего то же самое. [/ EDIT]
Встроенное представление дает вам простой «псевдоним» для сложного выражения, на которое вы затем можете ссылаться в предложении GROUP BY во внешнем запросе:
select count(d.callid)
, d.duration
from (select callid
, case
when callDuration >= 600 then 12
when callDuration >= 540 then 11
when callDuration >= 480 then 10
when callDuration >= 420 then 9
when callDuration >= 360 then 8
when callDuration >= 300 then 7
when callDuration >= 240 then 6
when callDuration >= 180 then 5
when callDuration >= 120 then 4
when callDuration >= 60 then 3
when callDuration >= 30 then 2
when callDuration > 0 then 1
--else null
end as duration
from callmetatbl
where programid = 1001
and callDuration > 0
) d
group by d.duration
Давайте распакуем это.
d
) duration
из ] d
Этого должно быть достаточно, чтобы ответить на ваш вопрос. Если вы ищете эквивалентное выражение замены, то правильным ответом будет выражение из tekBlues ( +1! ) (оно работает на границе и для нецелых чисел.)
С заменой выражения из tekBlues (+1!):
select count(d.callid)
, d.duration
from (select callid
, case
when callduration >=30 and callduration<600
then floor(callduration/60)+2
when callduration>0 and callduration< 30
then 1
when callduration>=600
then 12
end as duration
from callmetatbl
where programid = 1001
and callDuration > 0
) d
group by d.duration
(Этого должно быть достаточно, чтобы ответить на ваш вопрос.
[ОБНОВЛЕНИЕ:] пример пользовательская функция (замена встроенного выражения CASE)
CREATE FUNCTION [dev].[udf_duration](@cd FLOAT)
RETURNS SMALLINT
AS
BEGIN
DECLARE @bucket SMALLINT
SET @bucket =
CASE
WHEN @cd >= 600 THEN 12
WHEN @cd >= 540 THEN 11
WHEN @cd >= 480 THEN 10
WHEN @cd >= 420 THEN 9
WHEN @cd >= 360 THEN 8
WHEN @cd >= 300 THEN 7
WHEN @cd >= 240 THEN 6
WHEN @cd >= 180 THEN 5
WHEN @cd >= 120 THEN 4
WHEN @cd >= 60 THEN 3
WHEN @cd >= 30 THEN 2
WHEN @cd > 0 THEN 1
--ELSE NULL
END
RETURN @bucket
END
select count(callid)
, [dev].[udf_duration](callDuration)
from callmetatbl
where programid = 1001
and callDuration > 0
group by [dev].[udf_duration](callDuration)
ПРИМЕЧАНИЯ: имейте в виду, что пользовательская функция добавит накладные расходы и (конечно) добавит зависимость от другого объекта базы данных.
Этот пример функции эквивалентен исходному выражению. В выражении OP CASE нет пробелов, но оно ссылается на каждую «точку останова» дважды, я предпочитаю проверять только нижнюю границу. (CASE возвращается, когда условие выполнено. Выполнение тестов в обратном порядке позволяет необработанному случаю (<= 0 или NULL) не пройти без проверки, ELSE NULL
не является обязательным, но может быть добавлено для полноты.
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ
(Не забудьте проверить производительность и план оптимизатора, чтобы убедиться, что он такой же (или ненамного хуже) оригинала. Раньше у меня были проблемы с переносом предикатов во встроенное представление, не похоже, что это будет проблемой в вашем случае.)
сохраненное представление
Обратите внимание, что встроенное представление также может быть сохранено как определение представления в базе данных. Но нет никаких причин для этого, кроме как «скрыть» сложное выражение от вашего оператора.
упрощение сложного выражения
Другой способ сделать сложное выражение «проще» - использовать пользовательскую функцию. Но функция, определяемая пользователем, имеет свой собственный набор проблем (включая снижение производительности).
добавить «справочную» таблицу базы данных
В некоторых ответах рекомендуется добавить «справочную» таблицу в базу данных. Не думаю, что это действительно необходимо. Конечно, это можно сделать, и может иметь смысл, если вы хотите получить различные значения для длительности
из callDuration
на лету, без необходимости изменять свой запрос и ] без необходимости запускать какие-либо операторы DDL (например, для изменения определения представления или изменения пользовательской функции).
С присоединением к «поисковой» таблице одно преимущество состоит в том, что вы можете заставить запрос возвращать разные наборы результатов, просто выполняя операции DML с «поисковой» таблицей.
Но это же преимущество может быть недостатком.
Тщательно подумайте, действительно ли выгода перевешивает обратную сторону. Рассмотрим влияние, которое новая таблица окажет на модульное тестирование, как проверить, что содержимое справочной таблицы является действительным и не изменено (есть ли перекрытия? Есть ли пробелы?), влияние на текущее обслуживание кода (из-за дополнительной сложности).
некоторые БОЛЬШИЕ предположения
Многие ответы, приведенные здесь, похоже, предполагают, что callDuration
является типом данных INTEGER. Кажется, они упустили возможность того, что это не целое число, но, возможно, я пропустил этот самородок в вопросе.
Это довольно простой тестовый пример, чтобы продемонстрировать, что:
callDuration BETWEEN 0 AND 30
НЕ эквивалентно
callDuration > 0 AND callDuration < 30
] Есть ли причина, по которой вы не используете между
? Сами утверждения кейса выглядят неплохо. Если вам это действительно не нравится, вы можете бросить все это в таблицу и сопоставить.
Durations
------------------
low high value
0 30 1
31 60 2
и т. Д.
(SELECT value FROM Durations WHERE callDuration BETWEEN low AND high) as Duration
РЕДАКТИРОВАТЬ: Или, в случае, когда используются числа с плавающей запятой, и между
становится громоздким.
(SELECT value FROM Durations WHERE callDuration >= low AND callDuration <= high) as Duration
случай можно записать так:
case
when callduration >=30 and callduration<600 then floor(callduration/60)+2
when callduration>0 and callduration< 30 then 1
when callduration>=600 then 12
end
Наличие не требуется, замените его на "where callduration> 0"
Мне нравится приведенный выше ответ таблицы перевода! это лучшее решение
case
when callduration >=30 and callduration<600 then floor(callduration/60)+2
when callduration>0 and callduration< 30 then 1
when callduration>=600 then 12
end
Наличие не требуется, замените его на "where callduration> 0"
Мне нравится приведенный выше ответ таблицы перевода! это лучшее решение
case
when callduration >=30 and callduration<600 then floor(callduration/60)+2
when callduration>0 and callduration< 30 then 1
when callduration>=600 then 12
end
Наличие не требуется, замените его на "where callduration> 0"
Мне нравится приведенный выше ответ таблицы перевода! это лучшее решение
Вам нужно переместить CASE дальше вниз по дереву запроса, чтобы его проекция была видна для GROUP BY. Этого можно достичь двумя способами:
Использовать общие табличные выражения
с duration_case как (
выберите callid,
кейс
если callDuration> 0 и callDuration <30, то 1
если callDuration> = 30 и callDuration <60, то 2
если callDuration> = 60 и callDuration <120, то 3
если callDuration> = 120 и callDuration <180, то 4
если callDuration> = 180 и callDuration <240, то 5
если callDuration> = 240 и callDuration <300, то 6
если callDuration> = 300 и callDuration <360, то 7
если callDuration> = 360 и callDuration <420, то 8
если callDuration> = 420 и callDuration <480, то 9
если callDuration> = 480 и callDuration <540, то 10
если callDuration> = 540 и callDuration <600, то 11
если callDuration> = 600, то 12
конец как продолжительность
из callmetatbl
где programid = 1001 и callDuration> 0)
выберите количество (callid), продолжительность
from duration_case
группировать по продолжительности
Оба решения эквивалентны во всех отношениях. Я считаю CTE более читаемыми, некоторые предпочитают производные таблицы как более переносимые.
Разделите callDuration
на 60:
case
when callDuration between 1 AND 29 then 1
when callDuration > 600 then 12
else (callDuration /60) + 2 end
end as duration
Обратите внимание, что между
включает границы, и я предполагаю, что callDuration будет рассматривается как целое число.
Обновление:
Объедините это с некоторыми другими ответами, и вы сможете получить весь запрос до следующего:
select count(d.callid), d.duration
from (
select callid
, case
when callDuration between 1 AND 29 then 1
when callDuration > 600 then 12
else (callDuration /60) + 2 end
end as duration
from callmetatbl
where programid = 1001
and callDuration > 0
) d
group by d.duration
select count(callid), duration from
(
select callid ,
case
when callDuration > 0 and callDuration < 30 then 1
when callDuration >= 30 and callDuration < 60 then 2
when callDuration >= 60 and callDuration < 120 then 3
when callDuration >= 120 and callDuration < 180 then 4
when callDuration >= 180 and callDuration < 240 then 5
when callDuration >= 240 and callDuration < 300 then 6
when callDuration >= 300 and callDuration < 360 then 7
when callDuration >= 360 and callDuration < 420 then 8
when callDuration >= 420 and callDuration < 480 then 9
when callDuration >= 480 and callDuration < 540 then 10
when callDuration >= 540 and callDuration < 600 then 11
when callDuration >= 600 then 12
end as duration
from callmetatbl
where programid = 1001 and callDuration > 0
) source
group by duration
Непроверено:
select count(callid) , duracion
from
(select
callid,
case
when callDuration > 0 and callDuration < 30 then 1
when callDuration >= 30 and callDuration < 60 then 2
when callDuration >= 60 and callDuration < 120 then 3
when callDuration >= 120 and callDuration < 180 then 4
when callDuration >= 180 and callDuration < 240 then 5
when callDuration >= 240 and callDuration < 300 then 6
when callDuration >= 300 and callDuration < 360 then 7
when callDuration >= 360 and callDuration < 420 then 8
when callDuration >= 420 and callDuration < 480 then 9
when callDuration >= 480 and callDuration < 540 then 10
when callDuration >= 540 and callDuration < 600 then 11
when callDuration >= 600 then 12
else 0
end as duracion
from callmetatbl
where programid = 1001) GRP
where duracion > 0
group by duracion
Добавьте все наблюдения в переменную таблицы и выполните внешнее соединение
DECLARE @t TABLE(durationFrom INT, durationTo INT, result INT)
-- when callDuration > 0 and callDuration < 30 then 1
INSERT INTO @t VALUES(1, 30, 1);
-- when callDuration >= 30 and callDuration < 60 then 2
INSERT INTO @t VALUES(30, 60, 2);
select count(callid) , COALESCE(t.result, 12)
from callmetatbl JOIN @t AS t ON callDuration >= t.durationFrom AND callDuration < t.durationTo
where programid = 1001 and callDuration > 0
Что плохого здесь в функции, определяемой пользователем? Таким образом можно было как визуально очистить код, так и централизовать функциональность. С точки зрения производительности, я не вижу, чтобы результат был слишком ужасным, если вы не делаете что-то действительно отсталое в указанном UDF.
Here's my shot at it. All of the components you need can be done in straight SQL.
select
count(1) as total
,(fixedDuration / divisor) + adder as duration
from
(
select
case/*(30s_increments_else_60s)*/when(callDuration<60)then(120)else(60)end as divisor
,case/*(increment_by_1_else_2)*/when(callDuration<30)then(1)else(2)end as adder
,(/*duration_capped@600*/callDuration+600-ABS(callDuration-600))/2 as fixedDuration
,callDuration
from
callmetatbl
where
programid = 1001
and
callDuration > 0
) as foo
group by
(fixedDuration / divisor) + adder
Here's the SQL I used for testing. (I don't have my own personal callmetatbl ;)
select
count(1) as total
,(fixedDuration / divisor) + adder as duration
from
(
select
case/*(30s_increments_else_60s)*/when(callDuration<60)then(120)else(60)end as divisor
,case/*(increment_by_1_else_2)*/when(callDuration<30)then(1)else(2)end as adder
,(/*duration_capped@600*/callDuration+600-ABS(callDuration-600))/2 as fixedDuration
,callDuration
from -- callmetatbl -- using test view below
(
select 1001 as programid, 0 as callDuration union
select 1001 as programid, 1 as callDuration union
select 1001 as programid, 29 as callDuration union
select 1001 as programid, 30 as callDuration union
select 1001 as programid, 59 as callDuration union
select 1001 as programid, 60 as callDuration union
select 1001 as programid, 119 as callDuration union
select 1001 as programid, 120 as callDuration union
select 1001 as programid, 179 as callDuration union
select 1001 as programid, 180 as callDuration union
select 1001 as programid, 239 as callDuration union
select 1001 as programid, 240 as callDuration union
select 1001 as programid, 299 as callDuration union
select 1001 as programid, 300 as callDuration union
select 1001 as programid, 359 as callDuration union
select 1001 as programid, 360 as callDuration union
select 1001 as programid, 419 as callDuration union
select 1001 as programid, 420 as callDuration union
select 1001 as programid, 479 as callDuration union
select 1001 as programid, 480 as callDuration union
select 1001 as programid, 539 as callDuration union
select 1001 as programid, 540 as callDuration union
select 1001 as programid, 599 as callDuration union
select 1001 as programid, 600 as callDuration union
select 1001 as programid,1000 as callDuration
) as callmetatbl
where
programid = 1001
and
callDuration > 0
) as foo
group by
(fixedDuration / divisor) + adder
The SQL output is shown below, as 2 records counted for each duration (bucket) 1 through 12.
total duration
2 1
2 2
2 3
2 4
2 5
2 6
2 7
2 8
2 9
2 10
2 11
2 12
Here are the results from the "foo" sub-query:
divisor adder fixedDuration callDuration
120 1 1 1
120 1 29 29
120 2 30 30
120 2 59 59
60 2 60 60
60 2 119 119
60 2 120 120
60 2 179 179
60 2 180 180
60 2 239 239
60 2 240 240
60 2 299 299
60 2 300 300
60 2 359 359
60 2 360 360
60 2 419 419
60 2 420 420
60 2 479 479
60 2 480 480
60 2 539 539
60 2 540 540
60 2 599 599
60 2 600 600
60 2 600 1000
Cheers.
Создание таблицы поиска на длительность
Использование таблицы поиска также ускорит выполнение оператора SELECT
.
Вот конечный результат как это будет выглядеть с таблицей поиска.
select count(a.callid), b.ID as duration
from callmetatbl a
inner join DurationMap b
on a.callDuration >= b.Minimum
and a.callDuration < IsNUll(b.Maximum, a.CallDuration + 1)
group by b.ID
Вот таблица поиска.
create table DurationMap (
ID int identity(1,1) primary key,
Minimum int not null,
Maximum int
)
insert DurationMap(Minimum, Maximum) select 0,30
insert DurationMap(Minimum, Maximum) select 30,60
insert DurationMap(Minimum, Maximum) select 60,120
insert DurationMap(Minimum, Maximum) select 120,180
insert DurationMap(Minimum, Maximum) select 180,240
insert DurationMap(Minimum, Maximum) select 240,300
insert DurationMap(Minimum, Maximum) select 300,360
insert DurationMap(Minimum, Maximum) select 360,420
insert DurationMap(Minimum, Maximum) select 420,480
insert DurationMap(Minimum, Maximum) select 480,540
insert DurationMap(Minimum, Maximum) select 540,600
insert DurationMap(Minimum) select 600