diff -urN zabbix-2.0.7.orig/frontends/php/include/classes/validators/CTriggerFunctionValidator.php frontends/php/include/classes/validators/CTriggerFunctionValidator.php
--- zabbix-2.0.7.orig/frontends/php/include/classes/validators/CTriggerFunctionValidator.php	2013-07-31 01:33:03.000000000 -0700
+++ frontends/php/include/classes/validators/CTriggerFunctionValidator.php	2013-08-16 08:03:55.000000000 -0700
@@ -274,6 +274,14 @@
 				),
 				'value_types' => $valueTypesNum
 			),
+			'percentile' => array(
+				'args' => array(
+					array('type' => 'sec_num', 'mandat' => true),
+					array('type' => 'num', 'mandat' => true),
+					array('type' => 'sec')
+				),
+				'value_types' => $valueTypesNum
+			),
 			'nodata'=> array(
 				'args' => array(
 					array('type' => 'sec', 'mandat' => true)
diff -urN zabbix-2.0.7.orig/frontends/php/include/triggers.inc.php frontends/php/include/triggers.inc.php
--- zabbix-2.0.7.orig/frontends/php/include/triggers.inc.php	2013-07-31 01:33:03.000000000 -0700
+++ frontends/php/include/triggers.inc.php	2013-08-15 07:22:46.467720659 -0700
@@ -2229,6 +2229,7 @@
 		'logsource' =>	array('value_type' => _('0 or 1'),	'type' => T_ZBX_INT,			'validation' => IN('0,1')),
 		'max' =>		array('value_type' => $value_type,	'type' => $type_of_value_type,	'validation' => NOT_EMPTY),
 		'min' =>		array('value_type' => $value_type,	'type' => $type_of_value_type,	'validation' => NOT_EMPTY),
+		'percentile' =>	array('value_type' => $value_type,	'type' => $type_of_value_type,	'validation' => NOT_EMPTY),
 		'nodata' =>		array('value_type' => _('0 or 1'),	'type' => T_ZBX_INT,			'validation' => IN('0,1')),
 		'now' =>		array('value_type' => _('Numeric (integer 64bit)'), 'type' => T_ZBX_INT, 'validation' => NOT_EMPTY),
 		'prev' =>		array('value_type' => $value_type,	'type' => $type_of_value_type,	'validation' => NOT_EMPTY),
diff -urN zabbix-2.0.7.orig/frontends/php/popup_trexpr.php frontends/php/popup_trexpr.php
--- zabbix-2.0.7.orig/frontends/php/popup_trexpr.php	2013-07-31 01:33:05.000000000 -0700
+++ frontends/php/popup_trexpr.php	2013-08-16 15:11:22.000000000 -0700
@@ -78,6 +78,22 @@
 		'M' => $metrics // metrcis
 	)
 );
+$param2_pcnt_sec_count = array(
+	array(
+		'C' => _('Last of').' (T)',	/* caption */
+		'T' => T_ZBX_INT,	/* type */
+		'M' => $metrics		/* metrcis */
+	),
+		array(
+		'C' => 'Percentile (P)', /* caption */
+		'T' => T_ZBX_STR /* I would use T_ZBX_INT but then we get "seconds" text after the parameter box. */
+	),
+	array(
+		'C' => _('Time shift').' ', // caption
+		'T' => T_ZBX_INT // type
+	)
+);
+
 $param3_sec_val = array(
 	array(
 		'C' => _('Last of').' (T)', // caption
@@ -278,7 +294,27 @@
 		'params' => $param1_sec_count,
 		'allowed_types' => $allowed_types_numeric
 		),
-	'prev[<]' => array(
+	'percentile[<]' => array(
+		'description' =>  _('Pth percentile for period T is < N'),
+		'params' => $param2_pcnt_sec_count,
+		'allowed_types' => $allowed_types_numeric
+		),
+	'percentile[>]' => array(
+		'description' =>  _('Pth percentile for period T is > N'),
+		'params' => $param2_pcnt_sec_count,
+		'allowed_types' => $allowed_types_numeric
+		),
+	'percentile[=]' => array(
+		'description' =>  _('Pth percentile for period T is = N'),
+		'params' => $param2_pcnt_sec_count,
+		'allowed_types' => $allowed_types_numeric
+		),
+	'percentile[#]' => array(
+		'description' =>  _('Pth percentile for period T is NOT N'),
+		'params' => $param2_pcnt_sec_count,
+		'allowed_types' => $allowed_types_numeric
+		),
+		'prev[<]' => array(
 		'description' =>  _('Previous value is < N'),
 		'allowed_types' => $allowed_types_any
 	),
diff -urN zabbix-2.0.7.orig/src/libs/zbxserver/evalfunc.c src/libs/zbxserver/evalfunc.c
--- zabbix-2.0.7.orig/src/libs/zbxserver/evalfunc.c	2013-07-31 01:33:02.000000000 -0700
+++ src/libs/zbxserver/evalfunc.c	2013-08-19 08:01:29.000000000 -0700
@@ -29,6 +29,25 @@
 	return fabs(a - b) < TRIGGER_EPSILON ? SUCCEED : FAIL;
 }
 
+int	compare_uint64(const void *uint64_1, const void *uint64_2) {
+	if (*(zbx_uint64_t *)uint64_1 > *(zbx_uint64_t *)uint64_2)
+		return 1;
+	else if (*(zbx_uint64_t *)uint64_1 < *(zbx_uint64_t *)uint64_2)
+		return -1;
+	else
+		return 0;
+}
+
+int	compare_float(const void *float1, const void *float2) {
+	if (*(double *)float1 > *(double *)float2)
+		return 1;
+	else if (*(double *)float1 < *(double *)float2)
+		return -1;
+	else
+		return 0;
+
+}
+
 static int	get_function_parameter_uint(zbx_uint64_t hostid, const char *parameters, int Nparam, int *value, int *flag)
 {
 	const char	*__function_name = "get_function_parameter_uint";
@@ -1123,6 +1142,151 @@
 
 /******************************************************************************
  *                                                                            *
+ * Function: evaluate_PERCENTILE                                              *
+ *                                                                            *
+ * Purpose: evaluate function 'percentile' for the item                       *
+ *                                                                            *
+ * Parameters: item - item (performance metric)                               *
+ *             parameters - percent and number of seconds/values              *
+ *                                                                            *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ *               FAIL - failed to evaluate function                           *
+ *                                                                            *
+ * Author: Matthew Gould                                                      *
+ *         Based on patch for Zabbix 1.8 by Sergey Kononenko                  *
+ *                                                                            *
+ * Comments:                                                                  *
+ *                                                                            *
+ ******************************************************************************/
+static int	evaluate_PERCENTILE(char *value, DB_ITEM *item, const char *function, const char *parameters, time_t now)
+{
+	const char	*__function_name = "evaluate_PERCENTILE";
+	int		nparams, percent, percent_index, period, flag, percent_flag, rows = 0, rows_alloc = 60, res = FAIL;
+	zbx_uint64_t    pct_uint64;
+	char		**h_value;
+	zbx_uint64_t    *auint64 = NULL;
+	double          *afloat = NULL;
+
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
+
+	if (item->value_type != ITEM_VALUE_TYPE_FLOAT && item->value_type != ITEM_VALUE_TYPE_UINT64)
+		goto clean;
+
+	nparams = num_param(parameters);
+	if (!(nparams == 2 || nparams == 3))
+		goto clean;
+
+	if (FAIL == get_function_parameter_uint(item->hostid, parameters, 1, &period, &flag))
+		goto clean;
+
+	if (FAIL == get_function_parameter_uint(item->hostid, parameters, 2, &percent, &percent_flag))
+		goto clean;
+
+	if (nparams == 3)
+	{
+		int time_shift, time_shift_flag;
+
+		if (FAIL == get_function_parameter_uint(item->hostid, parameters, 3, &time_shift, &time_shift_flag))
+			goto clean;
+
+		if (time_shift_flag != ZBX_FLAG_SEC)
+			goto clean;
+
+		now -= time_shift;
+	}
+
+	if (percent < 0 || percent > 100)
+	{
+		zabbix_log(LOG_LEVEL_WARNING, "Invalid result for %d PERCENTILE", percent);
+		goto clean;
+	}
+
+	if (flag == ZBX_FLAG_SEC)
+	{
+		h_value = DBget_history(item->itemid, item->value_type, ZBX_DB_GET_HIST_VALUE,
+				now - period, now, NULL, NULL, 0);
+	}
+	else if (flag == ZBX_FLAG_VALUES)
+	{
+		h_value = DBget_history(item->itemid, item->value_type, ZBX_DB_GET_HIST_VALUE,
+				0, now, NULL, NULL, period);
+	}
+
+	if (item->value_type == ITEM_VALUE_TYPE_UINT64)
+	{
+		auint64 = zbx_malloc(auint64, sizeof(zbx_uint64_t) * rows_alloc);
+
+		for (rows = 0; NULL != h_value[rows]; rows++)
+		{
+			if (rows == rows_alloc)
+			{
+				rows_alloc += 60;
+				auint64 = zbx_realloc(auint64, sizeof(zbx_uint64_t) * rows_alloc);
+			}
+			ZBX_STR2UINT64(auint64[rows], h_value[rows]);
+		}
+	}
+	else
+	{
+		afloat = zbx_malloc(afloat, sizeof(double) * rows_alloc);
+
+		for (rows = 0; NULL != h_value[rows]; rows++)
+		{
+			if (rows == rows_alloc)
+			{
+				rows_alloc += 60;
+				afloat = zbx_realloc(afloat, sizeof(double) * rows_alloc);
+			}
+			afloat[rows] = atof(h_value[rows]);
+		}
+	}
+
+	DBfree_history(h_value);
+
+	if (0 != rows)
+	{
+		if (100 == percent)
+		{
+			percent_index = rows-1;
+		}
+		else
+		{
+			percent_index = (int)((percent/100.0)*rows);
+		}
+
+		if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
+		{
+			qsort(auint64, rows, sizeof(zbx_uint64_t), compare_uint64);
+			zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_UI64, auint64[percent_index]);
+		}
+		else
+		{
+			qsort(afloat, rows, sizeof(double), compare_float);
+			zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL, afloat[percent_index]);
+		}
+		res = SUCCEED;
+	}
+	else
+		zabbix_log(LOG_LEVEL_DEBUG, "result for PERCENTILE is empty");
+
+	if (item->value_type == ITEM_VALUE_TYPE_UINT64)
+	{
+		zbx_free(auint64);
+	}
+	else
+	{
+		zbx_free(afloat);
+	}
+
+
+clean:
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res));
+
+	return res;
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: evaluate_DELTA                                                   *
  *                                                                            *
  * Purpose: evaluate function 'delta' for the item                            *
@@ -1850,6 +2014,10 @@
 	{
 		ret = evaluate_MAX(value, item, function, parameter, now);
 	}
+	else if (0 == strcmp(function, "percentile"))
+	{
+		ret = evaluate_PERCENTILE(value, item, function, parameter, now);
+	}
 	else if (0 == strcmp(function, "avg"))
 	{
 		ret = evaluate_AVG(value, item, function, parameter, now);
diff -urN zabbix-2.0.7.orig/src/libs/zbxserver/evalfunc.h src/libs/zbxserver/evalfunc.h
--- zabbix-2.0.7.orig/src/libs/zbxserver/evalfunc.h	2013-07-31 01:33:02.000000000 -0700
+++ src/libs/zbxserver/evalfunc.h	2013-08-15 07:24:56.886899880 -0700
@@ -29,6 +29,8 @@
 extern int     CONFIG_SERVER_STARTUP_TIME;
 
 int	cmp_double(double a, double b);
+int	compare_float(const void *float1, const void *float2);
+int	compare_uint64(const void *uint64_1, const void *uint64_2);
 
 int	evaluate_macro_function(char *value, const char *host, const char *key,
 		const char *function, const char *parameter);
